├── .gitignore ├── IotaApi.Standard.Tests ├── IotaApi.Standard.Tests.csproj ├── IotaApiTests.cs ├── IotaCoreApiTest.cs ├── Pow │ ├── KerlTest.cs │ ├── LocalPoWTest.cs │ └── PearlDiverTest.cs └── Utils │ ├── BigIntConverterTest.cs │ ├── ChecksumTest.cs │ ├── InputValidatorTests.cs │ ├── IotaUnitConverterTests.cs │ ├── MultisigTest.cs │ ├── SigningTest.cs │ └── TrytesConverterTest.cs ├── IotaApi.Standard ├── Core │ ├── AddNeighborsRequest.cs │ ├── AddNeighborsResponse.cs │ ├── AttachToTangleRequest.cs │ ├── AttachToTangleResponse.cs │ ├── BroadcastTransactionsRequest.cs │ ├── BroadcastTransactionsResponse.cs │ ├── Command.cs │ ├── EnumHelper.cs │ ├── ErrorResponse.cs │ ├── FindTransactionsRequest.cs │ ├── FindTransactionsResponse.cs │ ├── GenericIotaCoreApi.cs │ ├── GetBalancesRequest.cs │ ├── GetBalancesResponse.cs │ ├── GetInclusionStatesRequest.cs │ ├── GetInclusionStatesResponse.cs │ ├── GetNeighborsRequest.cs │ ├── GetNeighborsResponse.cs │ ├── GetNodeInfoRequest.cs │ ├── GetNodeInfoResponse.cs │ ├── GetTipsRequest.cs │ ├── GetTipsResponse.cs │ ├── GetTransactionsToApproveRequest.cs │ ├── GetTransactionsToApproveResponse.cs │ ├── GetTrytesRequest.cs │ ├── GetTrytesResponse.cs │ ├── IGenericIotaCoreApi.cs │ ├── ILocalPoW.cs │ ├── InterruptAttachingToTangleRequest.cs │ ├── InterruptAttachingToTangleResponse.cs │ ├── IotaCoreApi.cs │ ├── IotaRequest.cs │ ├── IotaResponse.cs │ ├── RemoveNeighborsRequest.cs │ ├── RemoveNeighborsResponse.cs │ ├── StoreTransactionsRequest.cs │ └── StoreTransactionsResponse.cs ├── Exception │ ├── IllegalAccessError.cs │ ├── IllegalStateException.cs │ ├── InvalidAddressException.cs │ ├── InvalidBundleException.cs │ ├── InvalidSignatureException.cs │ ├── InvalidTailTransactionException.cs │ ├── InvalidTryteException.cs │ ├── InvisibleBundleTransactionException.cs │ ├── IotaApiException.cs │ └── NotEnoughBalanceException.cs ├── IotaApi.Standard.csproj ├── IotaApi.cs ├── Model │ ├── AccountData.cs │ ├── Bundle.cs │ ├── Input.cs │ ├── Inputs.cs │ ├── Neighbor.cs │ ├── Signature.cs │ ├── Transaction.cs │ └── Transfer.cs ├── Pow │ ├── Curl.cs │ ├── CurlMode.cs │ ├── ICurl.cs │ ├── Kerl.cs │ ├── PearlDiver.cs │ ├── PearlDiverLocalPoW.cs │ └── Sponge.cs └── Utils │ ├── ArrayUtils.cs │ ├── BigIntConverter.cs │ ├── Checksum.cs │ ├── Constants.cs │ ├── Converter.cs │ ├── FixedBigIntConverter.cs │ ├── InputValidator.cs │ ├── IotaApiUtils.cs │ ├── IotaUnitConverter.cs │ ├── IotaUnits.cs │ ├── Multisig.cs │ ├── Rest │ ├── JsonSerializer.cs │ └── JsonWebClient.cs │ ├── Signing.cs │ └── TrytesConverter.cs ├── IotaApi.sln ├── IotaApi.sln.DotSettings ├── IotaCSharpApi ├── Api │ ├── Core │ │ ├── AddNeighborsRequest.cs │ │ ├── AddNeighborsResponse.cs │ │ ├── AttachToTangleRequest.cs │ │ ├── AttachToTangleResponse.cs │ │ ├── BroadcastTransactionsRequest.cs │ │ ├── BroadcastTransactionsResponse.cs │ │ ├── Command.cs │ │ ├── EnumHelper.cs │ │ ├── ErrorResponse.cs │ │ ├── FindTransactionsRequest.cs │ │ ├── FindTransactionsResponse.cs │ │ ├── GenericIotaCoreApi.cs │ │ ├── GetBalancesRequest.cs │ │ ├── GetBalancesResponse.cs │ │ ├── GetInclusionStatesRequest.cs │ │ ├── GetInclusionStatesResponse.cs │ │ ├── GetNeighborsRequest.cs │ │ ├── GetNeighborsResponse.cs │ │ ├── GetNodeInfoRequest.cs │ │ ├── GetNodeInfoResponse.cs │ │ ├── GetTipsRequest.cs │ │ ├── GetTipsResponse.cs │ │ ├── GetTransactionsToApproveRequest.cs │ │ ├── GetTransactionsToApproveResponse.cs │ │ ├── GetTrytesRequest.cs │ │ ├── GetTrytesResponse.cs │ │ ├── IGenericIotaCoreApi.cs │ │ ├── ILocalPoW.cs │ │ ├── InterruptAttachingToTangleRequest.cs │ │ ├── InterruptAttachingToTangleResponse.cs │ │ ├── IotaCoreApi.cs │ │ ├── IotaRequest.cs │ │ ├── IotaResponse.cs │ │ ├── RemoveNeighborsRequest.cs │ │ ├── RemoveNeighborsResponse.cs │ │ ├── StoreTransactionsRequest.cs │ │ └── StoreTransactionsResponse.cs │ ├── Exception │ │ ├── IllegalAccessError.cs │ │ ├── IllegalStateException.cs │ │ ├── InvalidAddressException.cs │ │ ├── InvalidBundleException.cs │ │ ├── InvalidSignatureException.cs │ │ ├── InvalidTailTransactionException.cs │ │ ├── InvalidTryteException.cs │ │ ├── InvisibleBundleTransactionException.cs │ │ ├── IotaApiException.cs │ │ └── NotEnoughBalanceException.cs │ ├── IotaApi.cs │ ├── Model │ │ ├── AccountData.cs │ │ ├── Bundle.cs │ │ ├── Input.cs │ │ ├── Inputs.cs │ │ ├── Neighbor.cs │ │ ├── Signature.cs │ │ ├── Transaction.cs │ │ └── Transfer.cs │ ├── Pow │ │ ├── Curl.cs │ │ ├── CurlMode.cs │ │ ├── ICurl.cs │ │ ├── Kerl.cs │ │ ├── PearlDiver.cs │ │ ├── PearlDiverLocalPoW.cs │ │ └── Sponge.cs │ └── Utils │ │ ├── ArrayUtils.cs │ │ ├── BigIntConverter.cs │ │ ├── Checksum.cs │ │ ├── Constants.cs │ │ ├── Converter.cs │ │ ├── FixedBigIntConverter.cs │ │ ├── InputValidator.cs │ │ ├── IotaApiUtils.cs │ │ ├── IotaUnitConverter.cs │ │ ├── IotaUnits.cs │ │ ├── Multisig.cs │ │ ├── Rest │ │ ├── JsonSerializer.cs │ │ └── JsonWebClient.cs │ │ ├── Signing.cs │ │ ├── TritsConverter.cs │ │ └── TrytesConverter.cs ├── App.config ├── IotaCSharpApi.csproj ├── IotaCSharpApi.csproj.DotSettings ├── Package.nuspec ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── IotaCSharpApiUnitTests ├── Api │ ├── IotaApiTests.cs │ ├── IotaCoreApiTest.cs │ ├── Pow │ │ ├── KerlTest.cs │ │ ├── LocalPoWTest.cs │ │ └── PearlDiverTest.cs │ └── Utils │ │ ├── BigIntConverterTest.cs │ │ ├── ChecksumTest.cs │ │ ├── InputValidatorTests.cs │ │ ├── IotaUnitConverterTests.cs │ │ ├── MultisigTest.cs │ │ ├── SigningTest.cs │ │ └── TrytesConverterTest.cs ├── IotaCSharpApiUnitTests.csproj ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── LICENSE ├── README.md ├── SandcastleHelpFileBuilder.shfbproj └── appveyor.yml /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | #RiderC# 136 | .idea/ 137 | *.*.iml 138 | 139 | #LightSwitch generated files 140 | GeneratedArtifacts/ 141 | _Pvt_Extensions/ 142 | ModelManifest.xml 143 | 144 | # ========================= 145 | # Windows detritus 146 | # ========================= 147 | 148 | # Windows image file caches 149 | Thumbs.db 150 | ehthumbs.db 151 | 152 | # Folder config file 153 | Desktop.ini 154 | 155 | # Recycle Bin used on file shares 156 | $RECYCLE.BIN/ 157 | 158 | # Mac desktop service store files 159 | .DS_Store 160 | 161 | 162 | # Sandcasle Output Folder 163 | Help/* 164 | /.vs/IotaApi 165 | /packages 166 | -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/IotaApi.Standard.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | false 7 | 8 | Iota.Api.Standard.Tests 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Pow/KerlTest.cs: -------------------------------------------------------------------------------- 1 | using Iota.Api.Standard.Pow; 2 | using Iota.Api.Standard.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Iota.Api.Standard.Tests.Pow 6 | { 7 | [TestClass] 8 | public class KerlTest 9 | { 10 | [TestMethod] 11 | public void ShouldCreateValidHash1() 12 | { 13 | var trits = Converter.ToTrits( 14 | "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"); 15 | var kerl = new Kerl(); 16 | kerl.Reset(); 17 | kerl.Absorb(trits, 0, trits.Length); 18 | var hashTrits = new int[trits.Length]; 19 | kerl.Squeeze(hashTrits, 0, 243); 20 | var hash = Converter.ToTrytes(hashTrits); 21 | Assert.AreEqual(hash, "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW"); 22 | } 23 | 24 | [TestMethod] 25 | public void ShouldCreateValidHash2() 26 | { 27 | var trits = Converter.ToTrits( 28 | "9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH"); 29 | var kerl = new Kerl(); 30 | kerl.Reset(); 31 | kerl.Absorb(trits, 0, trits.Length); 32 | var hashTrits = new int[trits.Length * 2]; 33 | kerl.Squeeze(hashTrits, 0, 243 * 2); 34 | var hash = Converter.ToTrytes(hashTrits); 35 | Assert.AreEqual(hash, 36 | "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); 37 | } 38 | 39 | [TestMethod] 40 | public void ShouldCreateValidHash3() 41 | { 42 | var trits = Converter.ToTrits( 43 | "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); 44 | var kerl = new Kerl(); 45 | kerl.Reset(); 46 | kerl.Absorb(trits, 0, trits.Length); 47 | var hashTrits = new int[trits.Length]; 48 | kerl.Squeeze(hashTrits, 0, 243 * 2); 49 | var hash = Converter.ToTrytes(hashTrits); 50 | Assert.AreEqual(hash, 51 | "LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX"); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Pow/LocalPoWTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Iota.Api.Standard.Model; 3 | using Iota.Api.Standard.Pow; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Iota.Api.Standard.Tests.Pow 7 | { 8 | [TestClass] 9 | public class LocalPoWTest 10 | { 11 | private static readonly string TEST_SEED1 = 12 | "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; 13 | 14 | private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = 15 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; 16 | 17 | private static readonly string TEST_MESSAGE = "JUSTANOTHERJOTATEST"; 18 | private static readonly string TEST_TAG = "JOTASPAM9999999999999999999"; 19 | private static readonly int MIN_WEIGHT_MAGNITUDE = 14; 20 | private static readonly int DEPTH = 9; 21 | 22 | private IotaApi _iotaClient; 23 | 24 | [TestInitialize] 25 | public void Setup() 26 | { 27 | _iotaClient = new IotaApi("node.iotawallet.info", 14265) 28 | { 29 | LocalPow = new PearlDiverLocalPoW() 30 | }; 31 | } 32 | 33 | [TestMethod] 34 | public void ShouldSendTransfer() 35 | { 36 | var transfers = new List 37 | { 38 | new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG) 39 | }; 40 | var result = _iotaClient.SendTransfer( 41 | TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), 42 | null, null, false, false); 43 | Assert.IsNotNull(result); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Pow/PearlDiverTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Iota.Api.Standard.Pow; 4 | using Iota.Api.Standard.Utils; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Iota.Api.Standard.Tests.Pow 8 | { 9 | [TestClass] 10 | public class PearlDiverTest 11 | { 12 | 13 | private const int TryteLength = 2673; 14 | private const int MinWeightMagnitude = 9; 15 | private const int NumCores = -1; // use n-1 cores 16 | 17 | private static readonly Random Random = new Random(); 18 | private PearlDiver _pearlDiver; 19 | private int[] _hashTrits; 20 | 21 | [TestInitialize] 22 | public void Setup() 23 | { 24 | _pearlDiver = new PearlDiver(); 25 | _hashTrits = new int[Sponge.HashLength]; 26 | } 27 | 28 | 29 | [TestMethod] 30 | public void TestRandomTryteHash() 31 | { 32 | string testTrytes = GetRandomTrytes(); 33 | 34 | string hash = GetHashFor(testTrytes); 35 | 36 | string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); 37 | 38 | bool success = InputValidator.IsNinesTrytes(subHash,subHash.Length); 39 | if (!success) 40 | { 41 | Console.WriteLine(testTrytes); 42 | } 43 | 44 | Assert.IsTrue(success, "The hash should have n nines"); 45 | } 46 | 47 | [TestMethod] 48 | [Ignore] 49 | public void TestRandomTryteHash100() 50 | { 51 | for (int i = 0; i < 100; i++) 52 | { 53 | string testTrytes = GetRandomTrytes(); 54 | 55 | string hash = GetHashFor(testTrytes); 56 | 57 | string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); 58 | 59 | bool success = InputValidator.IsNinesTrytes(subHash, subHash.Length); 60 | if (!success) 61 | { 62 | Console.WriteLine(testTrytes); 63 | } 64 | 65 | Assert.IsTrue(success, "The hash should have n nines"); 66 | } 67 | } 68 | 69 | private string GetRandomTrytes() 70 | { 71 | var trytes = new StringBuilder(); 72 | 73 | for (int i = 0; i < TryteLength; i++) 74 | { 75 | trytes.Append(Constants.TryteAlphabet[Random.Next(27)]); 76 | } 77 | 78 | return trytes.ToString(); 79 | } 80 | 81 | private string GetHashFor(string trytes) 82 | { 83 | Sponge curl = new Curl(CurlMode.CurlP81); 84 | int[] myTrits = Converter.ToTrits(trytes); 85 | 86 | bool result = _pearlDiver.Search(myTrits, MinWeightMagnitude, NumCores); 87 | 88 | Assert.IsTrue(result,"Search Failed"); 89 | 90 | curl.Absorb(myTrits, 0, myTrits.Length); 91 | curl.Squeeze(_hashTrits, 0, Sponge.HashLength); 92 | curl.Reset(); 93 | 94 | return Converter.ToTrytes(_hashTrits); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Utils/BigIntConverterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Iota.Api.Standard.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using Org.BouncyCastle.Math; 5 | 6 | namespace Iota.Api.Standard.Tests.Utils 7 | { 8 | [TestClass] 9 | public class BigIntConverterTest 10 | { 11 | private static readonly Random Random = new Random(); 12 | // trits<->BigInteger<->byte 13 | 14 | [TestMethod] 15 | public void TestTritsAndBigInt() 16 | { 17 | var inputTrits = new int[243]; 18 | for (var i = 0; i < inputTrits.Length; i++) inputTrits[i] = Random.Next(3) - 1; 19 | 20 | var bigInt = BigIntConverter.BigIntFromTrits(inputTrits, 0, inputTrits.Length); 21 | 22 | var outputTrits = new int[inputTrits.Length]; 23 | BigIntConverter.TritsFromBigInt(bigInt, outputTrits, 0, outputTrits.Length); 24 | 25 | for (var i = 0; i < inputTrits.Length; i++) Assert.AreEqual(inputTrits[i], outputTrits[i]); 26 | } 27 | 28 | [TestMethod] 29 | public void TestBigIntAndByte() 30 | { 31 | var bytes = new byte[48]; 32 | var bigInt0 = new BigInteger("-123456"); 33 | 34 | BigIntConverter.BytesFromBigInt(bigInt0, bytes, 0, bytes.Length); 35 | var bigInt1 = BigIntConverter.BigIntFromBytes(bytes, 0, bytes.Length); 36 | 37 | Assert.AreEqual(bigInt0, bigInt1); 38 | } 39 | 40 | [TestMethod] 41 | public void TestFixedBigInt() 42 | { 43 | var inputTrits = new int[243]; 44 | var outputTrits = new int[243]; 45 | var bytes = new byte[384 / 8]; 46 | 47 | for (var i = 0; i < inputTrits.Length; i++) inputTrits[i] = Random.Next(3) - 1; 48 | 49 | inputTrits[inputTrits.Length - 1] = 0; 50 | FixedBigIntConverter.FromTritsToBytes(inputTrits, bytes); 51 | FixedBigIntConverter.FromBytesToTrits(bytes, outputTrits); 52 | outputTrits[outputTrits.Length - 1] = 0; 53 | 54 | for (var i = 0; i < inputTrits.Length; i++) Assert.AreEqual(inputTrits[i], outputTrits[i]); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Utils/ChecksumTest.cs: -------------------------------------------------------------------------------- 1 | using Iota.Api.Standard.Utils; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Iota.Api.Standard.Tests.Utils 5 | { 6 | [TestClass] 7 | public class ChecksumTest 8 | { 9 | private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM = 10 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; 11 | 12 | private static readonly string TEST_ADDRESS_WITH_CHECKSUM = 13 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; 14 | 15 | [TestMethod] 16 | public void ShouldAddChecksum() 17 | { 18 | Assert.AreEqual(Checksum.AddChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); 19 | } 20 | 21 | [TestMethod] 22 | public void ShouldRemoveChecksum() 23 | { 24 | Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.RemoveChecksum(), TEST_ADDRESS_WITHOUT_CHECKSUM); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldIsValidChecksum() 29 | { 30 | Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.IsValidChecksum(), true); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Utils/IotaUnitConverterTests.cs: -------------------------------------------------------------------------------- 1 | using Iota.Api.Standard.Utils; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Iota.Api.Standard.Tests.Utils 5 | { 6 | [TestClass] 7 | public class IotaUnitConverterTest 8 | { 9 | [TestMethod] 10 | public void ShouldConvertUnitItoKi() 11 | { 12 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Iota, IotaUnits.Kilo), 1); 13 | } 14 | 15 | [TestMethod] 16 | public void ShouldConvertUnitKiToMi() 17 | { 18 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Kilo, IotaUnits.Mega), 1); 19 | } 20 | 21 | [TestMethod] 22 | public void ShouldConvertUnitMiToGi() 23 | { 24 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Mega, IotaUnits.Giga), 1); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldConvertUnitGiToTi() 29 | { 30 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Giga, IotaUnits.Terra), 1); 31 | } 32 | 33 | [TestMethod] 34 | public void ShouldConvertUnitTiToPi() 35 | { 36 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Terra, IotaUnits.Peta), 1); 37 | } 38 | 39 | [TestMethod] 40 | public void ShouldFindOptimizeUnitToDisplay() 41 | { 42 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1), IotaUnits.Iota); 43 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000), IotaUnits.Kilo); 44 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000), IotaUnits.Mega); 45 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000), IotaUnits.Giga); 46 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000L), IotaUnits.Terra); 47 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000000L), IotaUnits.Peta); 48 | } 49 | 50 | /*[TestMethod] 51 | public void shouldConvertRawIotaAmountToDisplayText() 52 | { 53 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1, false), "1 i"); 54 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000, false), "1 Ki"); 55 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000, false), "1 Mi"); 56 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000, false), "1 Gi"); 57 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L, false), "1 Ti"); 58 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L, false), "1 Pi"); 59 | }*/ 60 | } 61 | } -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Utils/MultisigTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Iota.Api.Standard.Model; 4 | using Iota.Api.Standard.Pow; 5 | using Iota.Api.Standard.Utils; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace Iota.Api.Standard.Tests.Utils 9 | { 10 | [TestClass] 11 | public class MultisigTest 12 | { 13 | private const string TestSeed1 = "ABCDFG"; 14 | private const string TestSeed2 = "FDSAG"; 15 | 16 | private const string RemainderAddress = 17 | "NZRALDYNVGJWUVLKDWFKJVNYLWQGCWYCURJIIZRLJIKSAIVZSGEYKTZRDBGJLOA9AWYJQB9IPWRAKUC9FBDRZJZXZG"; 18 | 19 | private const string ReceiveAddress = 20 | "ZGHXPZYDKXPEOSQTAQOIXEEI9K9YKFKCWKYYTYAUWXK9QZAVMJXWAIZABOXHHNNBJIEBEUQRTBWGLYMTX"; 21 | 22 | private const string TestTag = "JOTASPAM9999999999999999999"; 23 | 24 | 25 | private IotaApi _iotaClient; 26 | 27 | [TestInitialize] 28 | public void CreateApiClientInstance() 29 | { 30 | _iotaClient = new IotaApi("node.iotawallet.info", 14265); 31 | } 32 | 33 | [TestMethod] 34 | public void BasicMultiSigTest() 35 | { 36 | Multisig ms = new Multisig(); 37 | 38 | // First co-signer uses security level 3 and index 0 for the private key 39 | string digestOne = ms.GetDigest(TestSeed1, 3, 0); 40 | 41 | // We initiate the multisig address generation by absorbing the key digest 42 | ms.AddAddressDigest(new[] {digestOne}); 43 | 44 | // Second cosigner also uses security level 3 and index 0 for the private key 45 | string digestTwo = ms.GetDigest(TestSeed2, 3, 0); 46 | 47 | // Add the multisig by absorbing the second cosigners key digest 48 | ms.AddAddressDigest(new[] {digestTwo}); 49 | 50 | // finally we generate the multisig address itself 51 | string multiSigAddress = ms.FinalizeAddress(); 52 | 53 | Console.WriteLine("MultisigAddress = " + multiSigAddress); 54 | 55 | 56 | bool isValidMultisigAddress = ms.ValidateAddress(multiSigAddress, 57 | new[] {Converter.ToTrits(digestOne), Converter.ToTrits(digestTwo)}); 58 | 59 | Console.WriteLine("Is a valid multisig address " + isValidMultisigAddress); 60 | 61 | Assert.IsTrue(isValidMultisigAddress, "Address is not a valid multisigAddress"); 62 | 63 | List transfers = new List 64 | { 65 | new Transfer(ReceiveAddress, 999, "", TestTag) 66 | }; 67 | 68 | List trxs = 69 | _iotaClient.InitiateTransfer(6, multiSigAddress, RemainderAddress, transfers, true); 70 | 71 | Bundle bundle = new Bundle(trxs, trxs.Count); 72 | 73 | bundle = ms.AddSignature(bundle, multiSigAddress, ms.GetKey(TestSeed1, 0, 3)); 74 | 75 | bundle = ms.AddSignature(bundle, multiSigAddress, ms.GetKey(TestSeed2, 0, 3)); 76 | 77 | 78 | Signing sgn = new Signing(new Kerl()); 79 | 80 | bool isValidSignature = sgn.ValidateSignatures(bundle, multiSigAddress); 81 | Console.WriteLine("Result of multi-signature validation is " + isValidSignature); 82 | Assert.IsTrue(isValidSignature, "MultiSignature not valid"); 83 | 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /IotaApi.Standard.Tests/Utils/TrytesConverterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Iota.Api.Standard.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Iota.Api.Standard.Tests.Utils 7 | { 8 | [TestClass] 9 | public class TrytesConverterTest 10 | { 11 | private static readonly Random Random = new Random(); 12 | 13 | [TestMethod] 14 | public void ShouldConvertStringToTrytes() 15 | { 16 | Assert.AreEqual("IC", TrytesConverter.ToTrytes("Z")); 17 | Assert.AreEqual(TrytesConverter.ToTrytes("JOTA JOTA"), "TBYBCCKBEATBYBCCKB"); 18 | } 19 | 20 | [TestMethod] 21 | public void ShouldConvertTrytesToString() 22 | { 23 | Assert.AreEqual("Z", TrytesConverter.ToString("IC")); 24 | Assert.AreEqual(TrytesConverter.ToString("TBYBCCKBEATBYBCCKB"), "JOTA JOTA"); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldConvertBackAndForth() 29 | { 30 | var str = RandomString(1000); 31 | var back = TrytesConverter.ToString(TrytesConverter.ToTrytes(str)); 32 | Assert.AreEqual(str, back); 33 | } 34 | 35 | public static string RandomString(int length) 36 | { 37 | const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 38 | return new string(Enumerable.Repeat(chars, length) 39 | .Select(s => s[Random.Next(s.Length)]).ToArray()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/AddNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | 6 | /// 7 | /// This class represents the core API request 'AddNeighbors'. 8 | /// It is used to add a neighbor to the node 9 | /// 10 | /// 11 | public class AddNeighborsRequest : IotaRequest 12 | { 13 | /// 14 | /// Gets or sets the uris. 15 | /// 16 | /// 17 | /// The uris. 18 | /// 19 | public List Uris { get; set; } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The uris of the neighbors to add. 25 | public AddNeighborsRequest(List uris) : base(Core.Command.AddNeighbors.GetCommandString()) 26 | { 27 | Uris = uris; 28 | } 29 | 30 | /// 31 | /// Returns a that represents this instance. 32 | /// 33 | /// 34 | /// A that represents this instance. 35 | /// 36 | public override string ToString() 37 | { 38 | return $"{nameof(Uris)}: {string.Join(",", Uris)}"; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/AddNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | 4 | /// 5 | /// Response of 6 | /// 7 | public class AddNeighborsResponse 8 | { 9 | /// 10 | /// Gets the number of added neighbors. 11 | /// 12 | /// 13 | /// The number of added neighbors. 14 | /// 15 | public long AddedNeighbors { get; set; } 16 | 17 | /// 18 | /// Returns a that represents this instance. 19 | /// 20 | /// 21 | /// A that represents this instance. 22 | /// 23 | public override string ToString() 24 | { 25 | return $"{nameof(AddedNeighbors)}: {AddedNeighbors}"; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/AttachToTangleRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | 4 | /// 5 | /// This class represents the core API request 'AttachToTangle'. 6 | /// It is used to attach trytes to the tangle. 7 | /// 8 | public class AttachToTangleRequest : IotaRequest 9 | { 10 | private const int MinWeightMagnitudeMin = 18; 11 | private int _minWeightMagnitude = MinWeightMagnitudeMin; 12 | 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The trunk transaction. 17 | /// The branch transaction. 18 | /// The trytes. 19 | /// The minimum weight magnitude. 20 | public AttachToTangleRequest(string trunkTransaction, string branchTransaction, string[] trytes, 21 | int minWeightMagnitude = 18) : base(Core.Command.AttachToTangle.GetCommandString()) 22 | { 23 | TrunkTransaction = trunkTransaction; 24 | BranchTransaction = branchTransaction; 25 | Trytes = trytes; 26 | MinWeightMagnitude = minWeightMagnitude; 27 | 28 | if (Trytes == null) 29 | Trytes = new string[0]; 30 | } 31 | 32 | /// 33 | /// Proof of Work intensity. Minimum value is 18 34 | /// 35 | public int MinWeightMagnitude 36 | { 37 | get { return _minWeightMagnitude; } 38 | set 39 | { 40 | if (value > MinWeightMagnitudeMin) 41 | _minWeightMagnitude = value; 42 | } 43 | } 44 | 45 | /// 46 | /// Trunk transaction to approve. 47 | /// 48 | public string TrunkTransaction { get; set; } 49 | 50 | /// 51 | /// Branch transaction to approve. 52 | /// 53 | public string BranchTransaction { get; set; } 54 | 55 | /// 56 | /// List of trytes (raw transaction data) to attach to the tangle. 57 | /// 58 | public string[] Trytes { get; set; } 59 | 60 | /// 61 | /// Returns a that represents this instance. 62 | /// 63 | /// 64 | /// A that represents this instance. 65 | /// 66 | public override string ToString() 67 | { 68 | return $"{nameof(MinWeightMagnitude)}: {MinWeightMagnitude}, {nameof(TrunkTransaction)}: {TrunkTransaction}, {nameof(BranchTransaction)}: {BranchTransaction}, {nameof(Trytes)}: {Trytes}"; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/AttachToTangleResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class AttachToTangleResponse 9 | { 10 | /// 11 | /// Gets or sets the trytes. 12 | /// 13 | /// 14 | /// The trytes. 15 | /// 16 | public List Trytes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/BroadcastTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle 7 | /// 8 | public class BroadcastTransactionsRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The trytes. 14 | public BroadcastTransactionsRequest(List trytes) 15 | : base(Core.Command.BroadcastTransactions.GetCommandString()) 16 | { 17 | Trytes = trytes; 18 | } 19 | 20 | /// 21 | /// Gets or sets the trytes representing the transactions 22 | /// 23 | /// 24 | /// The trytes. 25 | /// 26 | public List Trytes { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/BroadcastTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// Response of 5 | /// 6 | public class BroadcastTransactionsResponse 7 | { 8 | // empty 9 | } 10 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/Command.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This enumeration defines the core API call commands 7 | /// 8 | public enum Command 9 | { 10 | /// 11 | /// Adds neighbours to the node 12 | /// 13 | [Description("addNeighbors")] AddNeighbors, 14 | 15 | /// 16 | /// Attaches to the tangle 17 | /// 18 | [Description("attachToTangle")] AttachToTangle, 19 | 20 | /// 21 | /// Broadcasts transactions 22 | /// 23 | [Description("broadcastTransactions")] BroadcastTransactions, 24 | 25 | /// 26 | /// Finds the transactions using different search criteria 27 | /// 28 | [Description("findTransactions")] FindTransactions, 29 | 30 | /// 31 | /// Gets the balances 32 | /// 33 | [Description("getBalances")] GetBalances, 34 | 35 | /// 36 | /// Gets the inclusion state 37 | /// 38 | [Description("getInclusionStates")] GetInclusionStates, 39 | 40 | /// 41 | /// Gets the neighbours of the node 42 | /// 43 | [Description("getNeighbors")] GetNeighbors, 44 | 45 | /// 46 | /// Get information about the node. 47 | /// 48 | [Description("getNodeInfo")] GetNodeInfo, 49 | 50 | /// 51 | /// Gets the tips of the node 52 | /// 53 | [Description("getTips")] GetTips, 54 | 55 | /// 56 | /// Gets the transactions to approve 57 | /// 58 | [Description("getTransactionsToApprove")] GetTransactionsToApprove, 59 | 60 | /// 61 | /// Gets the trytes 62 | /// 63 | [Description("getTrytes")] GetTrytes, 64 | 65 | /// 66 | /// Interrupt attaching to the tangle 67 | /// 68 | [Description("interruptAttachingToTangle")] InterruptAttachingToTangle, 69 | 70 | /// 71 | /// Removes neighbours from the node 72 | /// 73 | [Description("removeNeighbors")] RemoveNeighbors, 74 | 75 | /// 76 | /// Stores transactions 77 | /// 78 | [Description("storeTransactions")] StoreTransactions, 79 | 80 | /// 81 | /// Get Missing Transactions 82 | /// 83 | [Description("getMissingTransactions")] GetMissingTransactions, 84 | 85 | /// 86 | /// Check Consistency 87 | /// 88 | [Description("checkConsistency")] CheckConsistency, 89 | 90 | /// 91 | /// Were Addresses SpentFrom 92 | /// 93 | [Description("wereAddressesSpentFrom")] WereAddressesSpentFrom, 94 | 95 | } 96 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/EnumHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Reflection; 4 | 5 | namespace Iota.Api.Standard.Core 6 | { 7 | /// 8 | /// Helper class that extracts the command string corresponding to the different s 9 | /// 10 | public static class EnumHelper 11 | { 12 | /// 13 | /// Retrieve the description on the enum 14 | /// 15 | /// The Enumeration 16 | /// A string representing the friendly name 17 | public static string GetCommandString(this Enum en) 18 | { 19 | Type type = en.GetType(); 20 | 21 | MemberInfo[] memInfo = type.GetMember(en.ToString()); 22 | 23 | if (memInfo != null && memInfo.Length > 0) 24 | { 25 | object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 26 | 27 | if (attrs != null && attrs.Length > 0) 28 | { 29 | return ((DescriptionAttribute) attrs[0]).Description; 30 | } 31 | } 32 | 33 | return en.ToString(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | internal class ErrorResponse 4 | { 5 | public string Error { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/FindTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'FindTransactions' 7 | /// 8 | public class FindTransactionsRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The bundles. 14 | /// The addresses. 15 | /// The tags. 16 | /// The approvees. 17 | public FindTransactionsRequest(List bundles, List addresses, List tags, 18 | List approvees) : base(Core.Command.FindTransactions.GetCommandString()) 19 | { 20 | Bundles = bundles; 21 | Addresses = addresses; 22 | Tags = tags; 23 | Approvees = approvees; 24 | 25 | if (Bundles == null) 26 | Bundles = new List(); 27 | if (Addresses == null) 28 | Addresses = new List(); 29 | if (Tags == null) 30 | Tags = new List(); 31 | if (Approvees == null) 32 | Approvees = new List(); 33 | } 34 | 35 | /// 36 | /// Gets or sets the bundles. 37 | /// 38 | /// 39 | /// The bundles. 40 | /// 41 | public List Bundles { get; set; } 42 | 43 | /// 44 | /// Gets or sets the addresses. 45 | /// 46 | /// 47 | /// The addresses. 48 | /// 49 | public List Addresses { get; set; } 50 | 51 | /// 52 | /// Gets or sets the tags. 53 | /// 54 | /// 55 | /// The tags. 56 | /// 57 | public List Tags { get; set; } 58 | 59 | /// 60 | /// Gets or sets the approvees. 61 | /// 62 | /// 63 | /// The approvees. 64 | /// 65 | public List Approvees { get; set; } 66 | 67 | /// 68 | /// 69 | /// 70 | /// 71 | public bool ShouldSerializeBundles() 72 | { 73 | return Bundles.Count > 0; 74 | } 75 | 76 | /// 77 | /// 78 | /// 79 | /// 80 | public bool ShouldSerializeAddresses() 81 | { 82 | return Addresses.Count > 0; 83 | } 84 | 85 | /// 86 | /// 87 | /// 88 | /// 89 | public bool ShouldSerializeTags() 90 | { 91 | return Tags.Count > 0; 92 | } 93 | 94 | /// 95 | /// 96 | /// 97 | /// 98 | public bool ShouldSerializeApprovees() 99 | { 100 | return Approvees.Count > 0; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/FindTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class FindTransactionsResponse 9 | { 10 | /// 11 | /// Gets or sets the hashes. 12 | /// 13 | /// 14 | /// The hashes. 15 | /// 16 | public List Hashes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Hashes)}: {string.Join(",",Hashes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GenericIotaCoreApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Iota.Api.Standard.Utils.Rest; 3 | 4 | namespace Iota.Api.Standard.Core 5 | { 6 | /// 7 | /// This class represents a generic version of the core API that is used internally 8 | /// 9 | /// 10 | public class GenericIotaCoreApi : IGenericIotaCoreApi 11 | { 12 | private readonly string _host; 13 | private readonly int _port; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The host. 19 | /// The port. 20 | public GenericIotaCoreApi(string host, int port) 21 | { 22 | _host = host; 23 | _port = port; 24 | } 25 | 26 | /// 27 | /// Gets the hostname. 28 | /// 29 | /// 30 | /// The hostname. 31 | /// 32 | public string Hostname => _host; 33 | 34 | /// 35 | /// Gets the port. 36 | /// 37 | /// 38 | /// The port. 39 | /// 40 | public int Port => _port; 41 | 42 | /// 43 | /// Requests the specified request. 44 | /// 45 | /// The type of the request. 46 | /// The type of the response. 47 | /// The request. 48 | /// 49 | public TResponse Request(TRequest request) where TResponse : new() 50 | { 51 | JsonWebClient jsonWebClient = new JsonWebClient(); 52 | return jsonWebClient.GetPOSTResponseSync(new Uri(CreateBaseUrl()), 53 | new JsonSerializer().Serialize(request)); 54 | } 55 | 56 | /// 57 | /// Requests the specified request asynchronously 58 | /// 59 | /// The type of the request. 60 | /// The type of the response. 61 | /// The request. 62 | /// The response action. 63 | public void RequestAsync(TRequest request, Action responseAction) 64 | where TResponse : new() 65 | { 66 | JsonWebClient jsonWebClient = new JsonWebClient(); 67 | jsonWebClient.GetPOSTResponseAsync(new Uri(CreateBaseUrl()), 68 | new JsonSerializer().Serialize(request), responseAction); 69 | } 70 | 71 | private string CreateBaseUrl() 72 | { 73 | return "http://" + _host + ":" + _port; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetBalancesRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'GetBalances' 7 | /// 8 | public class GetBalancesRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The addresses. 14 | /// The threshold. 15 | public GetBalancesRequest(List addresses, long threshold = 100) 16 | : base(Core.Command.GetBalances.GetCommandString()) 17 | { 18 | Addresses = addresses; 19 | Threshold = threshold; 20 | } 21 | 22 | /// 23 | /// Gets the threshold. 24 | /// 25 | /// 26 | /// The threshold. 27 | /// 28 | public long Threshold { get; } 29 | 30 | /// 31 | /// Gets the addresses. 32 | /// 33 | /// 34 | /// The addresses. 35 | /// 36 | public List Addresses { get; } 37 | 38 | /// 39 | /// Returns a that represents this instance. 40 | /// 41 | /// 42 | /// A that represents this instance. 43 | /// 44 | public override string ToString() 45 | { 46 | return $"{nameof(Threshold)}: {Threshold}, {nameof(Addresses)}: {string.Join(",",Addresses)}"; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetBalancesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class GetBalancesResponse : IotaResponse 9 | { 10 | /// 11 | /// Gets or sets the balances. 12 | /// 13 | /// 14 | /// The balances. 15 | /// 16 | public List Balances { get; set; } 17 | 18 | /// 19 | /// Gets or sets the references. 20 | /// 21 | /// 22 | /// The references. 23 | /// 24 | public List References { get; set; } 25 | 26 | /// 27 | /// Gets or sets the index of the milestone. 28 | /// 29 | /// 30 | /// The index of the milestone. 31 | /// 32 | public int MilestoneIndex { get; set; } 33 | 34 | /// 35 | /// Returns a that represents this instance. 36 | /// 37 | /// 38 | /// A that represents this instance. 39 | /// 40 | public override string ToString() 41 | { 42 | return 43 | $"{nameof(Balances)}: {string.Join(",", Balances)}, {nameof(References)}: {string.Join(",", References)}, {nameof(MilestoneIndex)}: {MilestoneIndex}"; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetInclusionStatesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetInclusionStates' 5 | /// 6 | /// 7 | public class GetInclusionStatesRequest : IotaRequest 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The transactions. 13 | /// The tips. 14 | public GetInclusionStatesRequest(string[] transactions, string[] tips) 15 | : base(Core.Command.GetInclusionStates.GetCommandString()) 16 | { 17 | Transactions = transactions; 18 | Tips = tips; 19 | } 20 | 21 | /// 22 | /// Gets the transactions. 23 | /// 24 | /// 25 | /// The transactions. 26 | /// 27 | public string[] Transactions { get; } 28 | 29 | /// 30 | /// Gets the tips. 31 | /// 32 | /// 33 | /// The tips. 34 | /// 35 | public string[] Tips { get; } 36 | 37 | /// 38 | /// Returns a that represents this instance. 39 | /// 40 | /// 41 | /// A that represents this instance. 42 | /// 43 | public override string ToString() 44 | { 45 | return $"{nameof(Transactions)}: {Transactions}, {nameof(Tips)}: {Tips}"; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetInclusionStatesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | /// 9 | public class GetInclusionStatesResponse : IotaResponse 10 | { 11 | /// 12 | /// Gets or sets the states. 13 | /// 14 | /// 15 | /// The states. 16 | /// 17 | public List States { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetNeighbors' 5 | /// 6 | /// 7 | public class GetNeighborsRequest : IotaRequest 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public GetNeighborsRequest() : base(Core.Command.GetNeighbors.GetCommandString()) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Iota.Api.Standard.Model; 3 | 4 | namespace Iota.Api.Standard.Core 5 | { 6 | /// 7 | /// Response of 8 | /// 9 | public class GetNeighborsResponse 10 | { 11 | /// 12 | /// Gets or sets the neighbors. 13 | /// 14 | /// 15 | /// The neighbors. 16 | /// 17 | public List Neighbors { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetNodeInfoRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// Returns information about your node 5 | /// 6 | public class GetNodeInfoRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetNodeInfoRequest() : base(Core.Command.GetNodeInfo.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTipsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetTips' 5 | /// 6 | public class GetTipsRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetTipsRequest() : base(Core.Command.GetTips.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTipsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | public class GetTipsResponse : IotaResponse 9 | { 10 | /// 11 | /// Gets or sets the hashes. 12 | /// 13 | /// 14 | /// The hashes. 15 | /// 16 | public List Hashes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Hashes)}: {string.Join(",", Hashes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTransactionsToApproveRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core API call 'GetTransactionsToApprove' 5 | /// 6 | public class GetTransactionsToApproveRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The depth. 12 | public GetTransactionsToApproveRequest(int depth) 13 | : base(Core.Command.GetTransactionsToApprove.GetCommandString()) 14 | { 15 | Depth = depth; 16 | } 17 | 18 | /// 19 | /// Gets the depth. 20 | /// 21 | /// 22 | /// The depth. 23 | /// 24 | public int Depth { get; } 25 | 26 | /// 27 | /// Returns a that represents this instance. 28 | /// 29 | /// 30 | /// A that represents this instance. 31 | /// 32 | public override string ToString() 33 | { 34 | return $"{nameof(Depth)}: {Depth}"; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTransactionsToApproveResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class GetTransactionsToApproveResponse : IotaResponse 7 | { 8 | /// 9 | /// Gets or sets the trunk transaction. 10 | /// 11 | /// 12 | /// The trunk transaction. 13 | /// 14 | public string TrunkTransaction { get; set; } 15 | 16 | /// 17 | /// Gets or sets the branch transaction. 18 | /// 19 | /// 20 | /// The branch transaction. 21 | /// 22 | public string BranchTransaction { get; set; } 23 | 24 | /// 25 | /// Returns a that represents this instance. 26 | /// 27 | /// 28 | /// A that represents this instance. 29 | /// 30 | public override string ToString() 31 | { 32 | return $"{nameof(TrunkTransaction)}: {TrunkTransaction}, {nameof(BranchTransaction)}: {BranchTransaction}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTrytesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetTrytes' 5 | /// 6 | public class GetTrytesRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetTrytesRequest() : base(Core.Command.GetTrytes.GetCommandString()) 12 | { 13 | 14 | } 15 | 16 | /// 17 | /// Gets or sets the hashes. 18 | /// 19 | /// 20 | /// The hashes. 21 | /// 22 | public string[] Hashes { get; set; } 23 | 24 | /// 25 | /// Returns a that represents this instance. 26 | /// 27 | /// 28 | /// A that represents this instance. 29 | /// 30 | public override string ToString() 31 | { 32 | return $"{nameof(Hashes)}: {string.Join(",", Hashes)}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/GetTrytesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | public class GetTrytesResponse 9 | { 10 | 11 | /// 12 | /// Gets or sets the trytes. 13 | /// 14 | /// 15 | /// The trytes. 16 | /// 17 | public List Trytes { get; set; } 18 | 19 | /// 20 | /// Returns a that represents this instance. 21 | /// 22 | /// 23 | /// A that represents this instance. 24 | /// 25 | public override string ToString() 26 | { 27 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/IGenericIotaCoreApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This interface abstracts a generic version of the core api that is used internally. 7 | /// 8 | public interface IGenericIotaCoreApi 9 | { 10 | /// 11 | /// Gets the hostname. 12 | /// 13 | /// 14 | /// The hostname. 15 | /// 16 | string Hostname { get; } 17 | 18 | /// 19 | /// Gets the port. 20 | /// 21 | /// 22 | /// The port. 23 | /// 24 | int Port { get; } 25 | 26 | /// 27 | /// Requests the specified request. 28 | /// 29 | /// The type of the request. 30 | /// The type of the response. 31 | /// The request. 32 | /// 33 | TResponse Request(TRequest request) where TResponse : new(); 34 | 35 | /// 36 | /// Requests the specified request asynchronously 37 | /// 38 | /// The type of the request. 39 | /// The type of the response. 40 | /// The request. 41 | /// The response action. 42 | void RequestAsync(TRequest request, Action responseAction) 43 | where TResponse : new(); 44 | } 45 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/ILocalPoW.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// 5 | /// 6 | public interface ILocalPoW 7 | { 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | string PerformPoW(string trytes, int minWeightMagnitude); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /IotaApi.Standard/Core/InterruptAttachingToTangleRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the core api request 'InterruptAttachingToTangle' 5 | /// 6 | public class InterruptAttachingToTangleRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public InterruptAttachingToTangleRequest() : base(Core.Command.InterruptAttachingToTangle.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/InterruptAttachingToTangleResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | /// 7 | public class InterruptAttachingToTangleResponse : IotaResponse 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/IotaRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class serves as base class for the different core API calls/requests 5 | /// 6 | public class IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The command. 12 | public IotaRequest(string command) 13 | { 14 | Command = command; 15 | } 16 | 17 | /// 18 | /// Gets or sets the command. 19 | /// 20 | /// 21 | /// The command. 22 | /// 23 | public string Command { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/IotaResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the base class of different core API response classes 5 | /// 6 | public class IotaResponse 7 | { 8 | /// 9 | /// Gets or sets the duration. 10 | /// 11 | /// 12 | /// The duration. 13 | /// 14 | public long Duration { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/RemoveNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'RemoveNeighbors' 7 | /// 8 | /// 9 | public class RemoveNeighborsRequest : IotaRequest 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The uris. 15 | public RemoveNeighborsRequest(List uris) : base(Core.Command.RemoveNeighbors.GetCommandString()) 16 | { 17 | Uris = uris; 18 | } 19 | 20 | /// 21 | /// Gets or sets the uris of the neighbours to remove 22 | /// 23 | /// 24 | /// The uris of the neighbours to remove. 25 | /// 26 | public List Uris { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Uris)}: {string.Join(",", Uris)}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/RemoveNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class RemoveNeighborsResponse 7 | { 8 | /// 9 | /// Gets or sets the number of removed neighbors. 10 | /// 11 | /// 12 | /// The removed neighbors. 13 | /// 14 | public long RemovedNeighbors { get; set; } 15 | 16 | /// 17 | /// Returns a that represents this instance. 18 | /// 19 | /// 20 | /// A that represents this instance. 21 | /// 22 | public override string ToString() 23 | { 24 | return $"{nameof(RemovedNeighbors)}: {RemovedNeighbors}"; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Core/StoreTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Core 4 | { 5 | /// 6 | /// This class represents the core API request 'StoreTransactions'. 7 | /// It stores transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. 8 | /// 9 | public class StoreTransactionsRequest : IotaRequest 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The trytes. 15 | public StoreTransactionsRequest(List trytes) : base(Core.Command.StoreTransactions.GetCommandString()) 16 | { 17 | Trytes = trytes; 18 | } 19 | 20 | /// 21 | /// Gets or sets the trytes. 22 | /// 23 | /// 24 | /// The trytes. 25 | /// 26 | public List Trytes { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Trytes)}: {Trytes}"; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /IotaApi.Standard/Core/StoreTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class StoreTransactionsResponse 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/IllegalAccessError.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when certain core API calls on the node are disabled 5 | /// 6 | /// 7 | public class IllegalAccessError : System.Exception 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/IllegalStateException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when an illegal state is encountered 5 | /// 6 | /// 7 | public class IllegalStateException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The error. 13 | public IllegalStateException(string error):base(error) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvalidAddressException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Api.Standard.Exception 4 | { 5 | /// 6 | /// This exception occurs when an invalid address is provided 7 | /// 8 | /// 9 | public class InvalidAddressException : ArgumentException 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The address. 15 | public InvalidAddressException(string address) : base("The specified address '" + address + "' is invalid") 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvalidBundleException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This excpetions occurs if an invalid bundle was found or provided 5 | /// 6 | /// 7 | public class InvalidBundleException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The message that describes the error. 13 | public InvalidBundleException(string message) : base(message) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvalidSignatureException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when an invalid signature is encountered 5 | /// 6 | /// 7 | public class InvalidSignatureException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public InvalidSignatureException() :base("Invalid signature found") 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvalidTailTransactionException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception is thrown when an invalid tail transaction was encountered 5 | /// 6 | /// 7 | public class InvalidTailTransactionException : System.Exception 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvalidTryteException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when invalid trytes are encountered 5 | /// 6 | public class InvalidTryteException : System.Exception 7 | { 8 | 9 | } 10 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/InvisibleBundleTransactionException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when a bundle or transaction is not visible in the tangle 5 | /// 6 | /// 7 | public class InvisibleBundleTransactionException : System.Exception 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/IotaApiException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception encapsulates an error that occured while communicating with the node (for example during a core API call) 5 | /// 6 | /// 7 | public class IotaApiException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The error. 13 | public IotaApiException(string error) : base(error) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Exception/NotEnoughBalanceException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Exception 2 | { 3 | /// 4 | /// This exception occurs when a transfer fails because their is not enough balance to perform the transfer 5 | /// 6 | /// 7 | public class NotEnoughBalanceException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public NotEnoughBalanceException() : base("Not enough balance") 13 | { 14 | } 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// The total value. 20 | public NotEnoughBalanceException(long totalValue) : base("Not enough balance to transfer " + totalValue + " iota") 21 | { 22 | 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /IotaApi.Standard/IotaApi.Standard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | Iota.Api.Standard 6 | Iota.Api.Standard 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /IotaApi.Standard/Model/AccountData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Model 4 | { 5 | /// 6 | /// 7 | /// 8 | public class AccountData 9 | { 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public AccountData(List addresses, 18 | Bundle[] transferBundle, List inputList, long totalBalance) 19 | { 20 | Addresses = addresses; 21 | TransferBundle = transferBundle; 22 | InputList = inputList; 23 | TotalBalance = totalBalance; 24 | } 25 | 26 | /// 27 | /// 28 | /// 29 | public List Addresses { get; set; } 30 | 31 | /// 32 | /// 33 | /// 34 | public Bundle[] TransferBundle { get; set; } 35 | 36 | /// 37 | /// 38 | /// 39 | public List InputList { get; set; } 40 | 41 | /// 42 | /// 43 | /// 44 | public long TotalBalance { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /IotaApi.Standard/Model/Input.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Model 2 | { 3 | /// 4 | /// This class represents an Input 5 | /// 6 | public class Input 7 | { 8 | /// 9 | /// Gets or sets the address. 10 | /// 11 | /// 12 | /// The address. 13 | /// 14 | public string Address { get; set; } 15 | 16 | /// 17 | /// Gets or sets the balance. 18 | /// 19 | /// 20 | /// The balance. 21 | /// 22 | public long Balance { get; set; } 23 | 24 | /// 25 | /// Gets or sets the index of the key. 26 | /// 27 | /// 28 | /// The index of the key. 29 | /// 30 | public int KeyIndex { get; set; } 31 | 32 | /// 33 | /// Get or sets the security. 34 | /// 35 | /// 36 | /// The security. 37 | /// 38 | public int Security { get; set; } 39 | /// 40 | /// Returns a that represents this instance. 41 | /// 42 | /// 43 | /// A that represents this instance. 44 | /// 45 | public override string ToString() 46 | { 47 | return $"{nameof(Address)}: {Address}, {nameof(Balance)}: {Balance}, {nameof(KeyIndex)}: {KeyIndex}, {nameof(Security)}: {Security}"; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Model/Inputs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Iota.Api.Standard.Model 5 | { 6 | /// 7 | /// This class represents the Inputs 8 | /// 9 | public class Inputs 10 | { 11 | /// 12 | /// Gets or sets the inputs list. 13 | /// 14 | /// 15 | /// The inputs list. 16 | /// 17 | public List InputsList { get; set; } 18 | 19 | /// 20 | /// Gets or sets the total balance. 21 | /// 22 | /// 23 | /// The total balance. 24 | /// 25 | public long TotalBalance { get; set; } 26 | 27 | /// 28 | /// Returns a that represents this instance. 29 | /// 30 | /// 31 | /// A that represents this instance. 32 | /// 33 | public override string ToString() 34 | { 35 | return 36 | $"Inputs:\n {string.Join(",", InputsList.Select(i => "[" + i + "]" + "\n"))}{nameof(TotalBalance)}: {TotalBalance}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Model/Neighbor.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Model 2 | { 3 | /// 4 | /// This class represents a neigbhor 5 | /// 6 | public class Neighbor 7 | { 8 | /// 9 | /// Gets or sets the address. 10 | /// 11 | /// 12 | /// The address. 13 | /// 14 | public string Address { get; set; } 15 | 16 | /// 17 | /// Gets or sets the number of all transactions. 18 | /// 19 | /// 20 | /// The number of all transactions. 21 | /// 22 | public long NumberOfAllTransactions { get; set; } 23 | 24 | /// 25 | /// Gets or sets the number of invalid transactions. 26 | /// 27 | /// 28 | /// The number of invalid transactions. 29 | /// 30 | public long NumberOfInvalidTransactions { get; set; } 31 | 32 | /// 33 | /// Gets or sets the number of new transactions. 34 | /// 35 | /// 36 | /// The number of new transactions. 37 | /// 38 | public long NumberOfNewTransactions { get; set; } 39 | 40 | /// 41 | /// Returns a that represents this instance. 42 | /// 43 | /// 44 | /// A that represents this instance. 45 | /// 46 | public override string ToString() 47 | { 48 | return $"{nameof(Address)}: {Address}, {nameof(NumberOfAllTransactions)}: {NumberOfAllTransactions}, {nameof(NumberOfInvalidTransactions)}: {NumberOfInvalidTransactions}, {nameof(NumberOfNewTransactions)}: {NumberOfNewTransactions}"; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Model/Signature.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Api.Standard.Model 4 | { 5 | /// 6 | /// Thic class represents a signature 7 | /// 8 | public class Signature 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public Signature() 14 | { 15 | SignatureFragments = new List(); 16 | } 17 | 18 | /// 19 | /// Gets or sets the address. 20 | /// 21 | /// 22 | /// The address. 23 | /// 24 | public string Address { get; set; } 25 | 26 | /// 27 | /// Gets or sets the signature fragments. 28 | /// 29 | /// 30 | /// The signature fragments. 31 | /// 32 | public List SignatureFragments { get; set; } 33 | 34 | /// 35 | /// Returns a that represents this instance. 36 | /// 37 | /// 38 | /// A that represents this instance. 39 | /// 40 | public override string ToString() 41 | { 42 | return $"{nameof(Address)}: {Address}, {nameof(SignatureFragments)}: {string.Join(",", SignatureFragments)}"; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Model/Transfer.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Model 2 | { 3 | /// 4 | /// This class represents a Transfer 5 | /// 6 | public class Transfer 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The address. 12 | /// The value. 13 | /// The message. 14 | /// The tag. 15 | public Transfer(string address, long value, string message, string tag) 16 | { 17 | Address = address; 18 | Value = value; 19 | Message = message; 20 | Tag = tag; 21 | } 22 | 23 | /// 24 | /// Gets or sets the address. 25 | /// 26 | /// 27 | /// The address. 28 | /// 29 | public string Address { get; set; } 30 | 31 | /// 32 | /// Gets or sets the hash. 33 | /// 34 | /// 35 | /// The hash. 36 | /// 37 | public string Hash { get; set; } 38 | 39 | /// 40 | /// Gets or sets the persistence. 41 | /// 42 | /// 43 | /// The persistence. 44 | /// 45 | public int Persistence { get; set; } 46 | 47 | /// 48 | /// Gets or sets the timestamp. 49 | /// 50 | /// 51 | /// The timestamp. 52 | /// 53 | public string Timestamp { get; set; } 54 | 55 | /// 56 | /// Gets or sets the value. 57 | /// 58 | /// 59 | /// The value. 60 | /// 61 | public long Value { get; set; } 62 | 63 | /// 64 | /// Gets or sets the message. 65 | /// 66 | /// 67 | /// The message. 68 | /// 69 | public string Message { get; set; } 70 | 71 | /// 72 | /// Gets or sets the tag. 73 | /// 74 | /// 75 | /// The tag. 76 | /// 77 | public string Tag { get; set; } 78 | 79 | /// 80 | /// Returns a that represents this instance. 81 | /// 82 | /// 83 | /// A that represents this instance. 84 | /// 85 | public override string ToString() 86 | { 87 | return $"{nameof(Address)}: {Address}, {nameof(Hash)}: {Hash}, {nameof(Message)}: {Message}, {nameof(Persistence)}: {Persistence}, {nameof(Tag)}: {Tag}, {nameof(Timestamp)}: {Timestamp}, {nameof(Value)}: {Value}"; 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Pow/CurlMode.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Pow 2 | { 3 | /// 4 | /// 5 | /// 6 | public enum CurlMode 7 | { 8 | /// 9 | /// 10 | /// 11 | CurlP81, 12 | /// 13 | /// 14 | /// 15 | CurlP27, 16 | /// 17 | /// 18 | /// 19 | Kerl 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /IotaApi.Standard/Pow/ICurl.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Pow 2 | { 3 | /// 4 | /// This interface abstracts the curl hashing algorithm 5 | /// 6 | public interface ICurl 7 | { 8 | /// 9 | /// Absorbs the specified trits. 10 | /// 11 | /// The trits. 12 | /// The offset to start from. 13 | /// The length. 14 | /// the ICurl instance (used for method chaining) 15 | void Absorb(int[] trits, int offset, int length); 16 | 17 | /// 18 | /// Absorbs the specified trits. 19 | /// 20 | /// The trits. 21 | /// the ICurl instance (used for method chaining) 22 | void Absorb(int[] trits); 23 | 24 | /// 25 | /// Squeezes the specified trits. 26 | /// 27 | /// The trits. 28 | /// The offset to start from. 29 | /// The length. 30 | /// the squeezed trits 31 | void Squeeze(int[] trits, int offset, int length); 32 | 33 | /// 34 | /// Squeezes the specified trits. 35 | /// 36 | /// The trits. 37 | /// the squeezed trits 38 | void Squeeze(int[] trits); 39 | 40 | 41 | /// 42 | /// Resets this state. 43 | /// 44 | /// the ICurl instance (used for method chaining) 45 | void Reset(); 46 | 47 | /// 48 | /// 49 | /// 50 | /// 51 | ICurl Clone(); 52 | } 53 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Pow/PearlDiverLocalPoW.cs: -------------------------------------------------------------------------------- 1 | using Iota.Api.Standard.Core; 2 | using Iota.Api.Standard.Exception; 3 | using Iota.Api.Standard.Utils; 4 | 5 | namespace Iota.Api.Standard.Pow 6 | { 7 | /// 8 | /// 9 | public class PearlDiverLocalPoW : ILocalPoW 10 | { 11 | private readonly PearlDiver _pearlDiver = new PearlDiver(); 12 | 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | public string PerformPoW(string trytes, int minWeightMagnitude) 20 | { 21 | var trits = Converter.ToTrits(trytes); 22 | 23 | if (!_pearlDiver.Search(trits, minWeightMagnitude, 0)) 24 | throw new IllegalStateException("PearlDiver search failed"); 25 | 26 | return Converter.ToTrytes(trits); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Pow/Sponge.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Pow 2 | { 3 | /// 4 | /// 5 | /// 6 | public abstract class Sponge : ICurl 7 | { 8 | 9 | /// 10 | /// 11 | /// 12 | public const int HashLength = 243; 13 | 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public abstract void Absorb(int[] trits, int offset, int length); 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | public void Absorb(int[] trits) => Absorb(trits,0,trits.Length); 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public abstract void Squeeze(int[] trits, int offset, int length); 36 | 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | public void Squeeze(int[] trits) => Squeeze(trits,0,trits.Length); 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | public abstract void Reset(); 49 | 50 | /// 51 | /// 52 | /// 53 | /// 54 | public abstract ICurl Clone(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/ArrayUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Iota.Api.Standard.Utils 5 | { 6 | internal class ArrayUtils 7 | { 8 | public static IEnumerable SliceRow(T[,] array, int row) 9 | { 10 | for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++) 11 | { 12 | yield return array[row, i]; 13 | } 14 | } 15 | 16 | public static T[] SubArray(T[] data, int startIndex, int endIndex) 17 | { 18 | int length = endIndex - startIndex; 19 | T[] result = new T[endIndex - startIndex]; 20 | Array.Copy(data, startIndex, result, 0, length); 21 | return result; 22 | } 23 | 24 | public static T[] SubArray2(T[] data, int index, int length) 25 | { 26 | T[] result = new T[length]; 27 | Array.Copy(data, index, result, 0, length); 28 | return result; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/BigIntConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Org.BouncyCastle.Math; 3 | 4 | namespace Iota.Api.Standard.Utils 5 | { 6 | /// 7 | /// 8 | /// 9 | public class BigIntConverter 10 | { 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static BigInteger BigIntFromTrits(int[] trits, int offset, int size) 19 | { 20 | var value = BigInteger.Zero; 21 | 22 | for (var i = size; i-- > 0;) 23 | value = value.Multiply(BigInteger.ValueOf(Converter.Radix)).Add(BigInteger.ValueOf(trits[offset + i])); 24 | 25 | return value; 26 | } 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public static BigInteger BigIntFromBytes(byte[] bytes, int offset, int size) 36 | { 37 | return new BigInteger(bytes, offset, size); 38 | } 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | public static void TritsFromBigInt(BigInteger value, int[] destination, int offset, int size) 49 | { 50 | if (destination.Length - offset < size) throw new ArgumentException("Destination array has invalid size"); 51 | 52 | var absoluteValue = value.CompareTo(BigInteger.Zero) < 0 ? value.Negate() : value; 53 | for (var i = 0; i < size; i++) 54 | { 55 | var divRemainder = absoluteValue.DivideAndRemainder(BigInteger.ValueOf(Converter.Radix)); 56 | var remainder = divRemainder[1].IntValue; 57 | absoluteValue = divRemainder[0]; 58 | 59 | if (remainder > Converter.MaxTritValue) 60 | { 61 | remainder = Converter.MinTritValue; 62 | absoluteValue = absoluteValue.Add(BigInteger.One); 63 | } 64 | 65 | destination[offset + i] = remainder; 66 | } 67 | 68 | if (value.CompareTo(BigInteger.Zero) < 0) 69 | for (var i = 0; i < size; i++) 70 | destination[offset + i] = -destination[offset + i]; 71 | } 72 | 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | /// 79 | /// 80 | /// 81 | public static void BytesFromBigInt(BigInteger value, byte[] destination, int offset,int size) 82 | { 83 | if (destination.Length - offset < size) 84 | throw new ArgumentException("Destination array has invalid size."); 85 | 86 | var bytes = value.ToByteArray(); 87 | var i = 0; 88 | while (i + bytes.Length < size) destination[i++] = (byte) ((sbyte) bytes[0] < 0 ? -1 : 0); 89 | 90 | for (var j = bytes.Length; j-- > 0;) destination[i++] = bytes[bytes.Length - 1 - j]; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/Checksum.cs: -------------------------------------------------------------------------------- 1 | using Iota.Api.Standard.Exception; 2 | using Iota.Api.Standard.Pow; 3 | 4 | namespace Iota.Api.Standard.Utils 5 | { 6 | /// 7 | /// This class defines utility methods to add/remove the checksum to/from an address 8 | /// 9 | public static class Checksum 10 | { 11 | /// 12 | /// Adds the checksum to the specified address 13 | /// 14 | /// An address without checksum 15 | /// The address with the appended checksum 16 | /// is thrown when an invalid address is provided 17 | public static string AddChecksum(string address) 18 | { 19 | InputValidator.CheckAddress(address); 20 | var addressWithChecksum = address; 21 | addressWithChecksum += CalculateChecksum(address); 22 | return addressWithChecksum; 23 | } 24 | 25 | 26 | /// 27 | /// Removes the checksum from the specified address with checksum 28 | /// 29 | /// The address with checksum or without checksum. 30 | /// the specified address without checksum 31 | /// is thrown when the specified address is not an address with checksum 32 | public static string RemoveChecksum(this string address) 33 | { 34 | if (IsAddressWithChecksum(address)) return GetAddress(address); 35 | 36 | if (IsAddressWithoutChecksum(address)) return address; 37 | 38 | throw new InvalidAddressException(address); 39 | } 40 | 41 | 42 | internal static string GetAddress(string addressWithChecksum) 43 | { 44 | return addressWithChecksum.Substring(0, Constants.AddressLengthWithoutChecksum); 45 | } 46 | 47 | /// 48 | /// Determines whether the specified address with checksum has a valid checksum. 49 | /// 50 | /// The address with checksum. 51 | /// 52 | /// true if the specified address with checksum has a valid checksum [the specified address with checksum]; 53 | /// otherwise, false. 54 | /// 55 | public static bool IsValidChecksum(this string addressWithChecksum) 56 | { 57 | var addressWithoutChecksum = RemoveChecksum(addressWithChecksum); 58 | var adressWithRecalculateChecksum = addressWithoutChecksum + CalculateChecksum(addressWithoutChecksum); 59 | return adressWithRecalculateChecksum.Equals(addressWithChecksum); 60 | } 61 | 62 | 63 | private static bool IsAddressWithChecksum(string addressWithChecksum) 64 | { 65 | return InputValidator.IsAddress(addressWithChecksum) && 66 | addressWithChecksum.Length == Constants.AddressLengthWithChecksum; 67 | } 68 | 69 | private static bool IsAddressWithoutChecksum(string address) 70 | { 71 | return InputValidator.CheckAddress(address) && address.Length == Constants.AddressLengthWithoutChecksum; 72 | } 73 | 74 | private static string CalculateChecksum(string address) 75 | { 76 | // TODO inject curl 77 | ICurl curl = new Kerl(); 78 | curl.Reset(); 79 | curl.Absorb(Converter.ToTrits(address)); 80 | var checksumTrits = new int[Sponge.HashLength]; 81 | curl.Squeeze(checksumTrits); 82 | var checksum = Converter.ToTrytes(checksumTrits); 83 | return checksum.Substring(72, 9); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Utils 2 | { 3 | /// 4 | /// This class defines different constants that are used accros the library 5 | /// 6 | public static class Constants 7 | { 8 | /// 9 | /// This String contains all possible characters of the tryte alphabet 10 | /// 11 | public static readonly string TryteAlphabet = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 12 | 13 | /// 14 | /// The maximum seed length 15 | /// 16 | public static readonly int SeedLengthMax = 81; 17 | 18 | /// 19 | /// This String represents the empty hash consisting of '9' 20 | /// 21 | public static readonly string EmptyHash = 22 | "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; 23 | 24 | /// 25 | /// The length of an address without checksum 26 | /// 27 | public static readonly int AddressLengthWithoutChecksum = 81; 28 | 29 | /// 30 | /// The address length with checksum 31 | /// 32 | public static readonly int AddressLengthWithChecksum = 90; 33 | 34 | /// 35 | /// The length of an message 36 | /// 37 | public static int MessageLength = 2187; 38 | /// 39 | /// 40 | /// 41 | public static int TagLength = 27; 42 | } 43 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/IotaUnitConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Api.Standard.Utils 4 | { 5 | /// 6 | /// This class provides methods to convert Iota to different units 7 | /// 8 | public class IotaUnitConverter 9 | { 10 | /// 11 | /// Convert the iota amount 12 | /// 13 | /// amount 14 | /// the source unit e.g. the unit of amount 15 | /// the target unit 16 | /// the specified amount in the target unit 17 | public static double ConvertUnits(long amount, IotaUnits fromUnit, IotaUnits toUnit) 18 | { 19 | long amountInSource = (long) (amount*Math.Pow(10, (int) fromUnit)); 20 | return ConvertUnits(amountInSource, toUnit); 21 | } 22 | 23 | private static double ConvertUnits(long amount, IotaUnits toUnit) 24 | { 25 | int base10NormalizationExponent = (int) toUnit; 26 | return (amount/Math.Pow(10, base10NormalizationExponent)); 27 | } 28 | 29 | /// 30 | /// Finds the optimal unit to display the specified amount in 31 | /// 32 | /// amount 33 | /// the optimal IotaUnit 34 | public static IotaUnits FindOptimalIotaUnitToDisplay(long amount) 35 | { 36 | int length = (amount).ToString().Length; 37 | 38 | if (amount < 0) 39 | { 40 | // do not count "-" sign 41 | length -= 1; 42 | } 43 | 44 | IotaUnits units = IotaUnits.Iota; 45 | 46 | if (length >= 1 && length <= 3) 47 | { 48 | units = IotaUnits.Iota; 49 | } 50 | else if (length > 3 && length <= 6) 51 | { 52 | units = IotaUnits.Kilo; 53 | } 54 | else if (length > 6 && length <= 9) 55 | { 56 | units = IotaUnits.Mega; 57 | } 58 | else if (length > 9 && length <= 12) 59 | { 60 | units = IotaUnits.Giga; 61 | } 62 | else if (length > 12 && length <= 15) 63 | { 64 | units = IotaUnits.Terra; 65 | } 66 | else if (length > 15 && length <= 18) 67 | { 68 | units = IotaUnits.Peta; 69 | } 70 | return units; 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/IotaUnits.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Api.Standard.Utils 2 | { 3 | /// 4 | /// Iota Units 5 | /// 6 | public enum IotaUnits 7 | { 8 | /// 9 | /// The corresponding value is in iota. Same as 'None' () 10 | /// 11 | Iota = 0, 12 | 13 | /// 14 | /// The corresponding value is in iota. Same as 'Iota' () 15 | /// 16 | None = 0, 17 | 18 | /// 19 | /// 10^3 20 | /// 21 | Kilo = 3, 22 | 23 | /// 24 | /// 10^6 25 | /// 26 | Mega = 6, 27 | 28 | /// 29 | /// 10^9 30 | /// 31 | Giga = 9, 32 | 33 | /// 34 | /// 10^12 35 | /// 36 | Terra = 12, 37 | 38 | /// 39 | /// 10^15 40 | /// 41 | Peta = 15, 42 | } 43 | } -------------------------------------------------------------------------------- /IotaApi.Standard/Utils/TrytesConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Iota.Api.Standard.Utils 4 | { 5 | /// 6 | /// This class allows to convert between ASCII and tryte encoded strings 7 | /// 8 | public class TrytesConverter 9 | { 10 | /// 11 | /// Converts the ASCII encoded string to trytes 12 | /// 13 | /// ASCII encoded string 14 | /// tryte encoded string 15 | public static string ToTrytes(string inputString) 16 | { 17 | var trytes = new StringBuilder(); 18 | 19 | foreach (var input in inputString) 20 | { 21 | var asciiValue = input; 22 | 23 | // If not recognizable ASCII character, replace with space 24 | if (asciiValue > 255) asciiValue = ' '; 25 | 26 | trytes.Append(Constants.TryteAlphabet[asciiValue % 27]); 27 | trytes.Append(Constants.TryteAlphabet[asciiValue / 27]); 28 | } 29 | 30 | return trytes.ToString(); 31 | } 32 | 33 | /// 34 | /// Converts the specified tryte encoded String to ASCII 35 | /// 36 | /// tryte encoded string 37 | /// an ASCII encoded string 38 | public static string ToString(string inputTrytes) 39 | { 40 | var builder = new StringBuilder(); 41 | 42 | for (var i = 0; i < inputTrytes.Length; i += 2) 43 | { 44 | // get a trytes pair 45 | 46 | var firstValue = TryteToDecimal(inputTrytes[i]); 47 | var secondValue = TryteToDecimal(inputTrytes[i + 1]); 48 | var decimalValue = firstValue + secondValue * 27; 49 | 50 | builder.Append((char) decimalValue); 51 | } 52 | 53 | return builder.ToString(); 54 | } 55 | 56 | /// 57 | /// Tryte To Decimal, '9' = 0 58 | /// 59 | /// 60 | /// 61 | public static int TryteToDecimal(char tryte) 62 | { 63 | if (tryte == '9') 64 | return 0; 65 | 66 | return tryte - 'A' + 1; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /IotaApi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2015 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaCSharpApi", "IotaCSharpApi\IotaCSharpApi.csproj", "{FC2C2F96-49EA-4046-95BD-3B570BDD1E13}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaCSharpApiUnitTests", "IotaCSharpApiUnitTests\IotaCSharpApiUnitTests.csproj", "{FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard", "IotaApi.Standard\IotaApi.Standard.csproj", "{8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard.Tests", "IotaApi.Standard.Tests\IotaApi.Standard.Tests.csproj", "{1797EB77-756A-4B7C-94FD-FC86B7EB7930}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {FC2C2F96-49EA-4046-95BD-3B570BDD1E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {FC2C2F96-49EA-4046-95BD-3B570BDD1E13}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {FC2C2F96-49EA-4046-95BD-3B570BDD1E13}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {FC2C2F96-49EA-4046-95BD-3B570BDD1E13}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {953B5A71-F598-4C42-A718-80390ACB8FF8} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /IotaApi.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | POST -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/AddNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | 6 | /// 7 | /// This class represents the core API request 'AddNeighbors'. 8 | /// It is used to add a neighbor to the node 9 | /// 10 | /// 11 | public class AddNeighborsRequest : IotaRequest 12 | { 13 | /// 14 | /// Gets or sets the uris. 15 | /// 16 | /// 17 | /// The uris. 18 | /// 19 | public List Uris { get; set; } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The uris of the neighbors to add. 25 | public AddNeighborsRequest(List uris) : base(Core.Command.AddNeighbors.GetCommandString()) 26 | { 27 | Uris = uris; 28 | } 29 | 30 | /// 31 | /// Returns a that represents this instance. 32 | /// 33 | /// 34 | /// A that represents this instance. 35 | /// 36 | public override string ToString() 37 | { 38 | return $"{nameof(Uris)}: {string.Join(",", Uris)}"; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/AddNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | 4 | /// 5 | /// Response of 6 | /// 7 | public class AddNeighborsResponse 8 | { 9 | /// 10 | /// Gets the number of added neighbors. 11 | /// 12 | /// 13 | /// The number of added neighbors. 14 | /// 15 | public long AddedNeighbors { get; set; } 16 | 17 | /// 18 | /// Returns a that represents this instance. 19 | /// 20 | /// 21 | /// A that represents this instance. 22 | /// 23 | public override string ToString() 24 | { 25 | return $"{nameof(AddedNeighbors)}: {AddedNeighbors}"; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/AttachToTangleRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | 4 | /// 5 | /// This class represents the core API request 'AttachToTangle'. 6 | /// It is used to attach trytes to the tangle. 7 | /// 8 | public class AttachToTangleRequest : IotaRequest 9 | { 10 | private const int MinWeightMagnitudeMin = 18; 11 | private int _minWeightMagnitude = MinWeightMagnitudeMin; 12 | 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The trunk transaction. 17 | /// The branch transaction. 18 | /// The trytes. 19 | /// The minimum weight magnitude. 20 | public AttachToTangleRequest(string trunkTransaction, string branchTransaction, string[] trytes, 21 | int minWeightMagnitude = 18) : base(Core.Command.AttachToTangle.GetCommandString()) 22 | { 23 | TrunkTransaction = trunkTransaction; 24 | BranchTransaction = branchTransaction; 25 | Trytes = trytes; 26 | MinWeightMagnitude = minWeightMagnitude; 27 | 28 | if (Trytes == null) 29 | Trytes = new string[0]; 30 | } 31 | 32 | /// 33 | /// Proof of Work intensity. Minimum value is 18 34 | /// 35 | public int MinWeightMagnitude 36 | { 37 | get { return _minWeightMagnitude; } 38 | set 39 | { 40 | if (value > MinWeightMagnitudeMin) 41 | _minWeightMagnitude = value; 42 | } 43 | } 44 | 45 | /// 46 | /// Trunk transaction to approve. 47 | /// 48 | public string TrunkTransaction { get; set; } 49 | 50 | /// 51 | /// Branch transaction to approve. 52 | /// 53 | public string BranchTransaction { get; set; } 54 | 55 | /// 56 | /// List of trytes (raw transaction data) to attach to the tangle. 57 | /// 58 | public string[] Trytes { get; set; } 59 | 60 | /// 61 | /// Returns a that represents this instance. 62 | /// 63 | /// 64 | /// A that represents this instance. 65 | /// 66 | public override string ToString() 67 | { 68 | return $"{nameof(MinWeightMagnitude)}: {MinWeightMagnitude}, {nameof(TrunkTransaction)}: {TrunkTransaction}, {nameof(BranchTransaction)}: {BranchTransaction}, {nameof(Trytes)}: {Trytes}"; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/AttachToTangleResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class AttachToTangleResponse 9 | { 10 | /// 11 | /// Gets or sets the trytes. 12 | /// 13 | /// 14 | /// The trytes. 15 | /// 16 | public List Trytes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/BroadcastTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle 7 | /// 8 | public class BroadcastTransactionsRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The trytes. 14 | public BroadcastTransactionsRequest(List trytes) 15 | : base(Core.Command.BroadcastTransactions.GetCommandString()) 16 | { 17 | Trytes = trytes; 18 | } 19 | 20 | /// 21 | /// Gets or sets the trytes representing the transactions 22 | /// 23 | /// 24 | /// The trytes. 25 | /// 26 | public List Trytes { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/BroadcastTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// Response of 5 | /// 6 | public class BroadcastTransactionsResponse 7 | { 8 | // empty 9 | } 10 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/Command.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This enumeration defines the core API call commands 7 | /// 8 | public enum Command 9 | { 10 | /// 11 | /// Adds neighbours to the node 12 | /// 13 | [Description("addNeighbors")] AddNeighbors, 14 | 15 | /// 16 | /// Attaches to the tangle 17 | /// 18 | [Description("attachToTangle")] AttachToTangle, 19 | 20 | /// 21 | /// Broadcasts transactions 22 | /// 23 | [Description("broadcastTransactions")] BroadcastTransactions, 24 | 25 | /// 26 | /// Finds the transactions using different search criteria 27 | /// 28 | [Description("findTransactions")] FindTransactions, 29 | 30 | /// 31 | /// Gets the balances 32 | /// 33 | [Description("getBalances")] GetBalances, 34 | 35 | /// 36 | /// Gets the inclusion state 37 | /// 38 | [Description("getInclusionStates")] GetInclusionStates, 39 | 40 | /// 41 | /// Gets the neighbours of the node 42 | /// 43 | [Description("getNeighbors")] GetNeighbors, 44 | 45 | /// 46 | /// Get information about the node. 47 | /// 48 | [Description("getNodeInfo")] GetNodeInfo, 49 | 50 | /// 51 | /// Gets the tips of the node 52 | /// 53 | [Description("getTips")] GetTips, 54 | 55 | /// 56 | /// Gets the transactions to approve 57 | /// 58 | [Description("getTransactionsToApprove")] GetTransactionsToApprove, 59 | 60 | /// 61 | /// Gets the trytes 62 | /// 63 | [Description("getTrytes")] GetTrytes, 64 | 65 | /// 66 | /// Interrupt attaching to the tangle 67 | /// 68 | [Description("interruptAttachingToTangle")] InterruptAttachingToTangle, 69 | 70 | /// 71 | /// Removes neighbours from the node 72 | /// 73 | [Description("removeNeighbors")] RemoveNeighbors, 74 | 75 | /// 76 | /// Stores transactions 77 | /// 78 | [Description("storeTransactions")] StoreTransactions, 79 | 80 | /// 81 | /// Get Missing Transactions 82 | /// 83 | [Description("getMissingTransactions")] GetMissingTransactions, 84 | 85 | /// 86 | /// Check Consistency 87 | /// 88 | [Description("checkConsistency")] CheckConsistency, 89 | 90 | /// 91 | /// Were Addresses SpentFrom 92 | /// 93 | [Description("wereAddressesSpentFrom")] WereAddressesSpentFrom, 94 | 95 | } 96 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/EnumHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Reflection; 4 | 5 | namespace Iota.Lib.CSharp.Api.Core 6 | { 7 | /// 8 | /// Helper class that extracts the command string corresponding to the different s 9 | /// 10 | public static class EnumHelper 11 | { 12 | /// 13 | /// Retrieve the description on the enum 14 | /// 15 | /// The Enumeration 16 | /// A string representing the friendly name 17 | public static string GetCommandString(this Enum en) 18 | { 19 | Type type = en.GetType(); 20 | 21 | MemberInfo[] memInfo = type.GetMember(en.ToString()); 22 | 23 | if (memInfo.Length > 0) 24 | { 25 | object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 26 | 27 | if (attrs.Length > 0) 28 | { 29 | return ((DescriptionAttribute) attrs[0]).Description; 30 | } 31 | } 32 | 33 | return en.ToString(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | internal class ErrorResponse 4 | { 5 | public string Error { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/FindTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'FindTransactions' 7 | /// 8 | public class FindTransactionsRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The bundles. 14 | /// The addresses. 15 | /// The tags. 16 | /// The approvees. 17 | public FindTransactionsRequest(List bundles, List addresses, List tags, 18 | List approvees) : base(Core.Command.FindTransactions.GetCommandString()) 19 | { 20 | Bundles = bundles; 21 | Addresses = addresses; 22 | Tags = tags; 23 | Approvees = approvees; 24 | 25 | if (Bundles == null) 26 | Bundles = new List(); 27 | if (Addresses == null) 28 | Addresses = new List(); 29 | if (Tags == null) 30 | Tags = new List(); 31 | if (Approvees == null) 32 | Approvees = new List(); 33 | } 34 | 35 | /// 36 | /// Gets or sets the bundles. 37 | /// 38 | /// 39 | /// The bundles. 40 | /// 41 | public List Bundles { get; set; } 42 | 43 | /// 44 | /// Gets or sets the addresses. 45 | /// 46 | /// 47 | /// The addresses. 48 | /// 49 | public List Addresses { get; set; } 50 | 51 | /// 52 | /// Gets or sets the tags. 53 | /// 54 | /// 55 | /// The tags. 56 | /// 57 | public List Tags { get; set; } 58 | 59 | /// 60 | /// Gets or sets the approvees. 61 | /// 62 | /// 63 | /// The approvees. 64 | /// 65 | public List Approvees { get; set; } 66 | 67 | /// 68 | /// 69 | /// 70 | /// 71 | public bool ShouldSerializeBundles() 72 | { 73 | return Bundles.Count > 0; 74 | } 75 | 76 | /// 77 | /// 78 | /// 79 | /// 80 | public bool ShouldSerializeAddresses() 81 | { 82 | return Addresses.Count > 0; 83 | } 84 | 85 | /// 86 | /// 87 | /// 88 | /// 89 | public bool ShouldSerializeTags() 90 | { 91 | return Tags.Count > 0; 92 | } 93 | 94 | /// 95 | /// 96 | /// 97 | /// 98 | public bool ShouldSerializeApprovees() 99 | { 100 | return Approvees.Count > 0; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/FindTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class FindTransactionsResponse 9 | { 10 | /// 11 | /// Gets or sets the hashes. 12 | /// 13 | /// 14 | /// The hashes. 15 | /// 16 | public List Hashes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Hashes)}: {string.Join(",",Hashes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GenericIotaCoreApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Iota.Lib.CSharp.Api.Utils.Rest; 3 | 4 | namespace Iota.Lib.CSharp.Api.Core 5 | { 6 | /// 7 | /// This class represents a generic version of the core API that is used internally 8 | /// 9 | /// 10 | public class GenericIotaCoreApi : IGenericIotaCoreApi 11 | { 12 | private readonly string _host; 13 | private readonly int _port; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The host. 19 | /// The port. 20 | public GenericIotaCoreApi(string host, int port) 21 | { 22 | _host = host; 23 | _port = port; 24 | } 25 | 26 | /// 27 | /// Gets the hostname. 28 | /// 29 | /// 30 | /// The hostname. 31 | /// 32 | public string Hostname => _host; 33 | 34 | /// 35 | /// Gets the port. 36 | /// 37 | /// 38 | /// The port. 39 | /// 40 | public int Port => _port; 41 | 42 | /// 43 | /// Requests the specified request. 44 | /// 45 | /// The type of the request. 46 | /// The type of the response. 47 | /// The request. 48 | /// 49 | public TResponse Request(TRequest request) where TResponse : new() 50 | { 51 | JsonWebClient jsonWebClient = new JsonWebClient(); 52 | return jsonWebClient.GetPOSTResponseSync(new Uri(CreateBaseUrl()), 53 | new JsonSerializer().Serialize(request)); 54 | } 55 | 56 | /// 57 | /// Requests the specified request asynchronously 58 | /// 59 | /// The type of the request. 60 | /// The type of the response. 61 | /// The request. 62 | /// The response action. 63 | public void RequestAsync(TRequest request, Action responseAction) 64 | where TResponse : new() 65 | { 66 | JsonWebClient jsonWebClient = new JsonWebClient(); 67 | jsonWebClient.GetPOSTResponseAsync(new Uri(CreateBaseUrl()), 68 | new JsonSerializer().Serialize(request), responseAction); 69 | } 70 | 71 | private string CreateBaseUrl() 72 | { 73 | return "http://" + _host + ":" + _port; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetBalancesRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'GetBalances' 7 | /// 8 | public class GetBalancesRequest : IotaRequest 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The addresses. 14 | /// The threshold. 15 | public GetBalancesRequest(List addresses, long threshold = 100) 16 | : base(Core.Command.GetBalances.GetCommandString()) 17 | { 18 | Addresses = addresses; 19 | Threshold = threshold; 20 | } 21 | 22 | /// 23 | /// Gets the threshold. 24 | /// 25 | /// 26 | /// The threshold. 27 | /// 28 | public long Threshold { get; } 29 | 30 | /// 31 | /// Gets the addresses. 32 | /// 33 | /// 34 | /// The addresses. 35 | /// 36 | public List Addresses { get; } 37 | 38 | /// 39 | /// Returns a that represents this instance. 40 | /// 41 | /// 42 | /// A that represents this instance. 43 | /// 44 | public override string ToString() 45 | { 46 | return $"{nameof(Threshold)}: {Threshold}, {nameof(Addresses)}: {string.Join(",",Addresses)}"; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetBalancesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// Response of 7 | /// 8 | public class GetBalancesResponse : IotaResponse 9 | { 10 | /// 11 | /// Gets or sets the balances. 12 | /// 13 | /// 14 | /// The balances. 15 | /// 16 | public List Balances { get; set; } 17 | 18 | /// 19 | /// Gets or sets the references. 20 | /// 21 | /// 22 | /// The references. 23 | /// 24 | public List References { get; set; } 25 | 26 | /// 27 | /// Gets or sets the index of the milestone. 28 | /// 29 | /// 30 | /// The index of the milestone. 31 | /// 32 | public int MilestoneIndex { get; set; } 33 | 34 | /// 35 | /// Returns a that represents this instance. 36 | /// 37 | /// 38 | /// A that represents this instance. 39 | /// 40 | public override string ToString() 41 | { 42 | return 43 | $"{nameof(Balances)}: {string.Join(",", Balances)}, {nameof(References)}: {string.Join(",", References)}, {nameof(MilestoneIndex)}: {MilestoneIndex}"; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetInclusionStatesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetInclusionStates' 5 | /// 6 | /// 7 | public class GetInclusionStatesRequest : IotaRequest 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The transactions. 13 | /// The tips. 14 | public GetInclusionStatesRequest(string[] transactions, string[] tips) 15 | : base(Core.Command.GetInclusionStates.GetCommandString()) 16 | { 17 | Transactions = transactions; 18 | Tips = tips; 19 | } 20 | 21 | /// 22 | /// Gets the transactions. 23 | /// 24 | /// 25 | /// The transactions. 26 | /// 27 | public string[] Transactions { get; } 28 | 29 | /// 30 | /// Gets the tips. 31 | /// 32 | /// 33 | /// The tips. 34 | /// 35 | public string[] Tips { get; } 36 | 37 | /// 38 | /// Returns a that represents this instance. 39 | /// 40 | /// 41 | /// A that represents this instance. 42 | /// 43 | public override string ToString() 44 | { 45 | return $"{nameof(Transactions)}: {Transactions}, {nameof(Tips)}: {Tips}"; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetInclusionStatesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | /// 9 | public class GetInclusionStatesResponse : IotaResponse 10 | { 11 | /// 12 | /// Gets or sets the states. 13 | /// 14 | /// 15 | /// The states. 16 | /// 17 | public List States { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetNeighbors' 5 | /// 6 | /// 7 | public class GetNeighborsRequest : IotaRequest 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public GetNeighborsRequest() : base(Core.Command.GetNeighbors.GetCommandString()) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Iota.Lib.CSharp.Api.Model; 3 | 4 | namespace Iota.Lib.CSharp.Api.Core 5 | { 6 | /// 7 | /// Response of 8 | /// 9 | public class GetNeighborsResponse 10 | { 11 | /// 12 | /// Gets or sets the neighbors. 13 | /// 14 | /// 15 | /// The neighbors. 16 | /// 17 | public List Neighbors { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetNodeInfoRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// Returns information about your node 5 | /// 6 | public class GetNodeInfoRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetNodeInfoRequest() : base(Core.Command.GetNodeInfo.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTipsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetTips' 5 | /// 6 | public class GetTipsRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetTipsRequest() : base(Core.Command.GetTips.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTipsResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | public class GetTipsResponse : IotaResponse 9 | { 10 | /// 11 | /// Gets or sets the hashes. 12 | /// 13 | /// 14 | /// The hashes. 15 | /// 16 | public List Hashes { get; set; } 17 | 18 | /// 19 | /// Returns a that represents this instance. 20 | /// 21 | /// 22 | /// A that represents this instance. 23 | /// 24 | public override string ToString() 25 | { 26 | return $"{nameof(Hashes)}: {string.Join(",", Hashes)}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTransactionsToApproveRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core API call 'GetTransactionsToApprove' 5 | /// 6 | public class GetTransactionsToApproveRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The depth. 12 | public GetTransactionsToApproveRequest(int depth) 13 | : base(Core.Command.GetTransactionsToApprove.GetCommandString()) 14 | { 15 | Depth = depth; 16 | } 17 | 18 | /// 19 | /// Gets the depth. 20 | /// 21 | /// 22 | /// The depth. 23 | /// 24 | public int Depth { get; } 25 | 26 | /// 27 | /// Returns a that represents this instance. 28 | /// 29 | /// 30 | /// A that represents this instance. 31 | /// 32 | public override string ToString() 33 | { 34 | return $"{nameof(Depth)}: {Depth}"; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTransactionsToApproveResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class GetTransactionsToApproveResponse : IotaResponse 7 | { 8 | /// 9 | /// Gets or sets the trunk transaction. 10 | /// 11 | /// 12 | /// The trunk transaction. 13 | /// 14 | public string TrunkTransaction { get; set; } 15 | 16 | /// 17 | /// Gets or sets the branch transaction. 18 | /// 19 | /// 20 | /// The branch transaction. 21 | /// 22 | public string BranchTransaction { get; set; } 23 | 24 | /// 25 | /// Returns a that represents this instance. 26 | /// 27 | /// 28 | /// A that represents this instance. 29 | /// 30 | public override string ToString() 31 | { 32 | return $"{nameof(TrunkTransaction)}: {TrunkTransaction}, {nameof(BranchTransaction)}: {BranchTransaction}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTrytesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core API request 'GetTrytes' 5 | /// 6 | public class GetTrytesRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public GetTrytesRequest() : base(Core.Command.GetTrytes.GetCommandString()) 12 | { 13 | 14 | } 15 | 16 | /// 17 | /// Gets or sets the hashes. 18 | /// 19 | /// 20 | /// The hashes. 21 | /// 22 | public string[] Hashes { get; set; } 23 | 24 | /// 25 | /// Returns a that represents this instance. 26 | /// 27 | /// 28 | /// A that represents this instance. 29 | /// 30 | public override string ToString() 31 | { 32 | return $"{nameof(Hashes)}: {string.Join(",", Hashes)}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/GetTrytesResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the response of 7 | /// 8 | public class GetTrytesResponse 9 | { 10 | 11 | /// 12 | /// Gets or sets the trytes. 13 | /// 14 | /// 15 | /// The trytes. 16 | /// 17 | public List Trytes { get; set; } 18 | 19 | /// 20 | /// Returns a that represents this instance. 21 | /// 22 | /// 23 | /// A that represents this instance. 24 | /// 25 | public override string ToString() 26 | { 27 | return $"{nameof(Trytes)}: {string.Join(",", Trytes)}"; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/IGenericIotaCoreApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This interface abstracts a generic version of the core api that is used internally. 7 | /// 8 | public interface IGenericIotaCoreApi 9 | { 10 | /// 11 | /// Gets the hostname. 12 | /// 13 | /// 14 | /// The hostname. 15 | /// 16 | string Hostname { get; } 17 | 18 | /// 19 | /// Gets the port. 20 | /// 21 | /// 22 | /// The port. 23 | /// 24 | int Port { get; } 25 | 26 | /// 27 | /// Requests the specified request. 28 | /// 29 | /// The type of the request. 30 | /// The type of the response. 31 | /// The request. 32 | /// 33 | TResponse Request(TRequest request) where TResponse : new(); 34 | 35 | /// 36 | /// Requests the specified request asynchronously 37 | /// 38 | /// The type of the request. 39 | /// The type of the response. 40 | /// The request. 41 | /// The response action. 42 | void RequestAsync(TRequest request, Action responseAction) 43 | where TResponse : new(); 44 | } 45 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/ILocalPoW.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// 5 | /// 6 | public interface ILocalPoW 7 | { 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | string PerformPoW(string trytes, int minWeightMagnitude); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/InterruptAttachingToTangleRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the core api request 'InterruptAttachingToTangle' 5 | /// 6 | public class InterruptAttachingToTangleRequest : IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public InterruptAttachingToTangleRequest() : base(Core.Command.InterruptAttachingToTangle.GetCommandString()) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/InterruptAttachingToTangleResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | /// 7 | public class InterruptAttachingToTangleResponse : IotaResponse 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/IotaRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class serves as base class for the different core API calls/requests 5 | /// 6 | public class IotaRequest 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The command. 12 | public IotaRequest(string command) 13 | { 14 | this.Command = command; 15 | } 16 | 17 | /// 18 | /// Gets or sets the command. 19 | /// 20 | /// 21 | /// The command. 22 | /// 23 | public string Command { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/IotaResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the base class of different core API response classes 5 | /// 6 | public class IotaResponse 7 | { 8 | /// 9 | /// Gets or sets the duration. 10 | /// 11 | /// 12 | /// The duration. 13 | /// 14 | public long Duration { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/RemoveNeighborsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the core api request 'RemoveNeighbors' 7 | /// 8 | /// 9 | public class RemoveNeighborsRequest : IotaRequest 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The uris. 15 | public RemoveNeighborsRequest(List uris) : base(Core.Command.RemoveNeighbors.GetCommandString()) 16 | { 17 | Uris = uris; 18 | } 19 | 20 | /// 21 | /// Gets or sets the uris of the neighbours to remove 22 | /// 23 | /// 24 | /// The uris of the neighbours to remove. 25 | /// 26 | public List Uris { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Uris)}: {string.Join(",", Uris)}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/RemoveNeighborsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class RemoveNeighborsResponse 7 | { 8 | /// 9 | /// Gets or sets the number of removed neighbors. 10 | /// 11 | /// 12 | /// The removed neighbors. 13 | /// 14 | public long RemovedNeighbors { get; set; } 15 | 16 | /// 17 | /// Returns a that represents this instance. 18 | /// 19 | /// 20 | /// A that represents this instance. 21 | /// 22 | public override string ToString() 23 | { 24 | return $"{nameof(RemovedNeighbors)}: {RemovedNeighbors}"; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/StoreTransactionsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Core 4 | { 5 | /// 6 | /// This class represents the core API request 'StoreTransactions'. 7 | /// It stores transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. 8 | /// 9 | public class StoreTransactionsRequest : IotaRequest 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The trytes. 15 | public StoreTransactionsRequest(List trytes) : base(Core.Command.StoreTransactions.GetCommandString()) 16 | { 17 | this.Trytes = trytes; 18 | } 19 | 20 | /// 21 | /// Gets or sets the trytes. 22 | /// 23 | /// 24 | /// The trytes. 25 | /// 26 | public List Trytes { get; set; } 27 | 28 | /// 29 | /// Returns a that represents this instance. 30 | /// 31 | /// 32 | /// A that represents this instance. 33 | /// 34 | public override string ToString() 35 | { 36 | return $"{nameof(Trytes)}: {Trytes}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Core/StoreTransactionsResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Core 2 | { 3 | /// 4 | /// This class represents the response of 5 | /// 6 | public class StoreTransactionsResponse 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/IllegalAccessError.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception occurs when certain core API calls on the node are disabled 5 | /// 6 | /// 7 | public class IllegalAccessError : System.Exception 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/IllegalStateException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Lib.CSharp.Api.Exception 4 | { 5 | /// 6 | /// This exception occurs when an illegal state is encountered 7 | /// 8 | /// 9 | public class IllegalStateException : System.Exception 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The error. 15 | public IllegalStateException(string error):base(error) 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvalidAddressException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Lib.CSharp.Api.Exception 4 | { 5 | /// 6 | /// This exception occurs when an invalid address is provided 7 | /// 8 | /// 9 | public class InvalidAddressException : ArgumentException 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The address. 15 | public InvalidAddressException(string address) : base("The specified address '" + address + "' is invalid") 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvalidBundleException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This excpetions occurs if an invalid bundle was found or provided 5 | /// 6 | /// 7 | public class InvalidBundleException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The message that describes the error. 13 | public InvalidBundleException(string message) : base(message) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvalidSignatureException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception occurs when an invalid signature is encountered 5 | /// 6 | /// 7 | public class InvalidSignatureException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public InvalidSignatureException() :base("Invalid signature found") 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvalidTailTransactionException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception is thrown when an invalid tail transaction was encountered 5 | /// 6 | /// 7 | public class InvalidTailTransactionException : System.Exception 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvalidTryteException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception occurs when invalid trytes are encountered 5 | /// 6 | public class InvalidTryteException : System.Exception 7 | { 8 | 9 | } 10 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/InvisibleBundleTransactionException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception occurs when a bundle or transaction is not visible in the tangle 5 | /// 6 | /// 7 | public class InvisibleBundleTransactionException : System.Exception 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/IotaApiException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception encapsulates an error that occured while communicating with the node (for example during a core API call) 5 | /// 6 | /// 7 | public class IotaApiException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The error. 13 | public IotaApiException(string error) : base(error) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Exception/NotEnoughBalanceException.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Exception 2 | { 3 | /// 4 | /// This exception occurs when a transfer fails because their is not enough balance to perform the transfer 5 | /// 6 | /// 7 | public class NotEnoughBalanceException : System.Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public NotEnoughBalanceException() : base("Not enough balance") 13 | { 14 | } 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// The total value. 20 | public NotEnoughBalanceException(long totalValue) : base("Not enough balance to transfer " + totalValue + " iota") 21 | { 22 | 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/AccountData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Model 4 | { 5 | /// 6 | /// 7 | /// 8 | public class AccountData 9 | { 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public AccountData(List addresses, 18 | Bundle[] transferBundle, List inputList, long totalBalance) 19 | { 20 | Addresses = addresses; 21 | TransferBundle = transferBundle; 22 | InputList = inputList; 23 | TotalBalance = totalBalance; 24 | } 25 | 26 | /// 27 | /// 28 | /// 29 | public List Addresses { get; set; } 30 | 31 | /// 32 | /// 33 | /// 34 | public Bundle[] TransferBundle { get; set; } 35 | 36 | /// 37 | /// 38 | /// 39 | public List InputList { get; set; } 40 | 41 | /// 42 | /// 43 | /// 44 | public long TotalBalance { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/Input.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Model 2 | { 3 | /// 4 | /// This class represents an Input 5 | /// 6 | public class Input 7 | { 8 | /// 9 | /// Gets or sets the address. 10 | /// 11 | /// 12 | /// The address. 13 | /// 14 | public string Address { get; set; } 15 | 16 | /// 17 | /// Gets or sets the balance. 18 | /// 19 | /// 20 | /// The balance. 21 | /// 22 | public long Balance { get; set; } 23 | 24 | /// 25 | /// Gets or sets the index of the key. 26 | /// 27 | /// 28 | /// The index of the key. 29 | /// 30 | public int KeyIndex { get; set; } 31 | 32 | /// 33 | /// Get or sets the security. 34 | /// 35 | /// 36 | /// The security. 37 | /// 38 | public int Security { get; set; } 39 | /// 40 | /// Returns a that represents this instance. 41 | /// 42 | /// 43 | /// A that represents this instance. 44 | /// 45 | public override string ToString() 46 | { 47 | return $"{nameof(Address)}: {Address}, {nameof(Balance)}: {Balance}, {nameof(KeyIndex)}: {KeyIndex}, {nameof(Security)}: {Security}"; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/Inputs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Iota.Lib.CSharp.Api.Model 5 | { 6 | /// 7 | /// This class represents the Inputs 8 | /// 9 | public class Inputs 10 | { 11 | /// 12 | /// Gets or sets the inputs list. 13 | /// 14 | /// 15 | /// The inputs list. 16 | /// 17 | public List InputsList { get; set; } 18 | 19 | /// 20 | /// Gets or sets the total balance. 21 | /// 22 | /// 23 | /// The total balance. 24 | /// 25 | public long TotalBalance { get; set; } 26 | 27 | /// 28 | /// Returns a that represents this instance. 29 | /// 30 | /// 31 | /// A that represents this instance. 32 | /// 33 | public override string ToString() 34 | { 35 | return 36 | $"Inputs:\n {string.Join(",", InputsList.Select(i => "[" + i + "]" + "\n"))}{nameof(TotalBalance)}: {TotalBalance}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/Neighbor.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Model 2 | { 3 | /// 4 | /// This class represents a neigbhor 5 | /// 6 | public class Neighbor 7 | { 8 | /// 9 | /// Gets or sets the address. 10 | /// 11 | /// 12 | /// The address. 13 | /// 14 | public string Address { get; set; } 15 | 16 | /// 17 | /// Gets or sets the number of all transactions. 18 | /// 19 | /// 20 | /// The number of all transactions. 21 | /// 22 | public long NumberOfAllTransactions { get; set; } 23 | 24 | /// 25 | /// Gets or sets the number of invalid transactions. 26 | /// 27 | /// 28 | /// The number of invalid transactions. 29 | /// 30 | public long NumberOfInvalidTransactions { get; set; } 31 | 32 | /// 33 | /// Gets or sets the number of new transactions. 34 | /// 35 | /// 36 | /// The number of new transactions. 37 | /// 38 | public long NumberOfNewTransactions { get; set; } 39 | 40 | /// 41 | /// Returns a that represents this instance. 42 | /// 43 | /// 44 | /// A that represents this instance. 45 | /// 46 | public override string ToString() 47 | { 48 | return $"{nameof(Address)}: {Address}, {nameof(NumberOfAllTransactions)}: {NumberOfAllTransactions}, {nameof(NumberOfInvalidTransactions)}: {NumberOfInvalidTransactions}, {nameof(NumberOfNewTransactions)}: {NumberOfNewTransactions}"; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/Signature.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Iota.Lib.CSharp.Api.Model 4 | { 5 | /// 6 | /// Thic class represents a signature 7 | /// 8 | public class Signature 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public Signature() 14 | { 15 | SignatureFragments = new List(); 16 | } 17 | 18 | /// 19 | /// Gets or sets the address. 20 | /// 21 | /// 22 | /// The address. 23 | /// 24 | public string Address { get; set; } 25 | 26 | /// 27 | /// Gets or sets the signature fragments. 28 | /// 29 | /// 30 | /// The signature fragments. 31 | /// 32 | public List SignatureFragments { get; set; } 33 | 34 | /// 35 | /// Returns a that represents this instance. 36 | /// 37 | /// 38 | /// A that represents this instance. 39 | /// 40 | public override string ToString() 41 | { 42 | return $"{nameof(Address)}: {Address}, {nameof(SignatureFragments)}: {string.Join(",", SignatureFragments)}"; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Model/Transfer.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Model 2 | { 3 | /// 4 | /// This class represents a Transfer 5 | /// 6 | public class Transfer 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The address. 12 | /// The value. 13 | /// The message. 14 | /// The tag. 15 | public Transfer(string address, long value, string message, string tag) 16 | { 17 | Address = address; 18 | Value = value; 19 | Message = message; 20 | Tag = tag; 21 | } 22 | 23 | /// 24 | /// Gets or sets the address. 25 | /// 26 | /// 27 | /// The address. 28 | /// 29 | public string Address { get; set; } 30 | 31 | /// 32 | /// Gets or sets the hash. 33 | /// 34 | /// 35 | /// The hash. 36 | /// 37 | public string Hash { get; set; } 38 | 39 | /// 40 | /// Gets or sets the persistence. 41 | /// 42 | /// 43 | /// The persistence. 44 | /// 45 | public int Persistence { get; set; } 46 | 47 | /// 48 | /// Gets or sets the timestamp. 49 | /// 50 | /// 51 | /// The timestamp. 52 | /// 53 | public string Timestamp { get; set; } 54 | 55 | /// 56 | /// Gets or sets the value. 57 | /// 58 | /// 59 | /// The value. 60 | /// 61 | public long Value { get; set; } 62 | 63 | /// 64 | /// Gets or sets the message. 65 | /// 66 | /// 67 | /// The message. 68 | /// 69 | public string Message { get; set; } 70 | 71 | /// 72 | /// Gets or sets the tag. 73 | /// 74 | /// 75 | /// The tag. 76 | /// 77 | public string Tag { get; set; } 78 | 79 | /// 80 | /// Returns a that represents this instance. 81 | /// 82 | /// 83 | /// A that represents this instance. 84 | /// 85 | public override string ToString() 86 | { 87 | return $"{nameof(Address)}: {Address}, {nameof(Hash)}: {Hash}, {nameof(Message)}: {Message}, {nameof(Persistence)}: {Persistence}, {nameof(Tag)}: {Tag}, {nameof(Timestamp)}: {Timestamp}, {nameof(Value)}: {Value}"; 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Pow/CurlMode.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Pow 2 | { 3 | /// 4 | /// 5 | /// 6 | public enum CurlMode 7 | { 8 | /// 9 | /// 10 | /// 11 | CurlP81, 12 | /// 13 | /// 14 | /// 15 | CurlP27, 16 | /// 17 | /// 18 | /// 19 | Kerl 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Pow/ICurl.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Pow 2 | { 3 | /// 4 | /// This interface abstracts the curl hashing algorithm 5 | /// 6 | public interface ICurl 7 | { 8 | /// 9 | /// Absorbs the specified trits. 10 | /// 11 | /// The trits. 12 | /// The offset to start from. 13 | /// The length. 14 | /// the ICurl instance (used for method chaining) 15 | void Absorb(int[] trits, int offset, int length); 16 | 17 | /// 18 | /// Absorbs the specified trits. 19 | /// 20 | /// The trits. 21 | /// the ICurl instance (used for method chaining) 22 | void Absorb(int[] trits); 23 | 24 | /// 25 | /// Squeezes the specified trits. 26 | /// 27 | /// The trits. 28 | /// The offset to start from. 29 | /// The length. 30 | /// the squeezed trits 31 | void Squeeze(int[] trits, int offset, int length); 32 | 33 | /// 34 | /// Squeezes the specified trits. 35 | /// 36 | /// The trits. 37 | /// the squeezed trits 38 | void Squeeze(int[] trits); 39 | 40 | 41 | /// 42 | /// Resets this state. 43 | /// 44 | /// the ICurl instance (used for method chaining) 45 | void Reset(); 46 | 47 | /// 48 | /// 49 | /// 50 | /// 51 | ICurl Clone(); 52 | } 53 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Pow/PearlDiverLocalPoW.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Iota.Lib.CSharp.Api.Core; 3 | using Iota.Lib.CSharp.Api.Exception; 4 | using Iota.Lib.CSharp.Api.Utils; 5 | 6 | namespace Iota.Lib.CSharp.Api.Pow 7 | { 8 | /// 9 | /// 10 | public class PearlDiverLocalPoW : ILocalPoW 11 | { 12 | private readonly PearlDiver _pearlDiver = new PearlDiver(); 13 | 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public string PerformPoW(string trytes, int minWeightMagnitude) 21 | { 22 | var trits = Converter.ToTrits(trytes); 23 | 24 | if (!_pearlDiver.Search(trits, minWeightMagnitude, 0)) 25 | throw new IllegalStateException("PearlDiver search failed"); 26 | 27 | return Converter.ToTrytes(trits); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Pow/Sponge.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Pow 2 | { 3 | /// 4 | /// 5 | /// 6 | public abstract class Sponge : ICurl 7 | { 8 | 9 | /// 10 | /// 11 | /// 12 | public const int HashLength = 243; 13 | 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public abstract void Absorb(int[] trits, int offset, int length); 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | public void Absorb(int[] trits) => Absorb(trits,0,trits.Length); 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public abstract void Squeeze(int[] trits, int offset, int length); 36 | 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | public void Squeeze(int[] trits) => Squeeze(trits,0,trits.Length); 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | public abstract void Reset(); 49 | 50 | /// 51 | /// 52 | /// 53 | /// 54 | public abstract ICurl Clone(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/ArrayUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Iota.Lib.CSharp.Api.Utils 5 | { 6 | internal class ArrayUtils 7 | { 8 | public static IEnumerable SliceRow(T[,] array, int row) 9 | { 10 | for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++) 11 | { 12 | yield return array[row, i]; 13 | } 14 | } 15 | 16 | public static T[] SubArray(T[] data, int startIndex, int endIndex) 17 | { 18 | int length = endIndex - startIndex; 19 | T[] result = new T[endIndex - startIndex]; 20 | Array.Copy(data, startIndex, result, 0, length); 21 | return result; 22 | } 23 | 24 | public static T[] SubArray2(T[] data, int index, int length) 25 | { 26 | T[] result = new T[length]; 27 | Array.Copy(data, index, result, 0, length); 28 | return result; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/BigIntConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Org.BouncyCastle.Math; 3 | 4 | namespace Iota.Lib.CSharp.Api.Utils 5 | { 6 | /// 7 | /// 8 | /// 9 | public class BigIntConverter 10 | { 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static BigInteger BigIntFromTrits(int[] trits, int offset, int size) 19 | { 20 | var value = BigInteger.Zero; 21 | 22 | for (var i = size; i-- > 0;) 23 | value = value.Multiply(BigInteger.ValueOf(Converter.Radix)).Add(BigInteger.ValueOf(trits[offset + i])); 24 | 25 | return value; 26 | } 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public static BigInteger BigIntFromBytes(byte[] bytes, int offset, int size) 36 | { 37 | return new BigInteger(bytes, offset, size); 38 | } 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | public static void TritsFromBigInt(BigInteger value, int[] destination, int offset, int size) 49 | { 50 | if (destination.Length - offset < size) throw new ArgumentException("Destination array has invalid size"); 51 | 52 | var absoluteValue = value.CompareTo(BigInteger.Zero) < 0 ? value.Negate() : value; 53 | for (var i = 0; i < size; i++) 54 | { 55 | var divRemainder = absoluteValue.DivideAndRemainder(BigInteger.ValueOf(Converter.Radix)); 56 | var remainder = divRemainder[1].IntValue; 57 | absoluteValue = divRemainder[0]; 58 | 59 | if (remainder > Converter.MaxTritValue) 60 | { 61 | remainder = Converter.MinTritValue; 62 | absoluteValue = absoluteValue.Add(BigInteger.One); 63 | } 64 | 65 | destination[offset + i] = remainder; 66 | } 67 | 68 | if (value.CompareTo(BigInteger.Zero) < 0) 69 | for (var i = 0; i < size; i++) 70 | destination[offset + i] = -destination[offset + i]; 71 | } 72 | 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | /// 79 | /// 80 | /// 81 | public static void BytesFromBigInt(BigInteger value, byte[] destination, int offset,int size) 82 | { 83 | if (destination.Length - offset < size) 84 | throw new ArgumentException("Destination array has invalid size."); 85 | 86 | var bytes = value.ToByteArray(); 87 | var i = 0; 88 | while (i + bytes.Length < size) destination[i++] = (byte) ((sbyte) bytes[0] < 0 ? -1 : 0); 89 | 90 | for (var j = bytes.Length; j-- > 0;) destination[i++] = bytes[bytes.Length - 1 - j]; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/Checksum.cs: -------------------------------------------------------------------------------- 1 | using Iota.Lib.CSharp.Api.Exception; 2 | using Iota.Lib.CSharp.Api.Pow; 3 | 4 | namespace Iota.Lib.CSharp.Api.Utils 5 | { 6 | /// 7 | /// This class defines utility methods to add/remove the checksum to/from an address 8 | /// 9 | public static class Checksum 10 | { 11 | /// 12 | /// Adds the checksum to the specified address 13 | /// 14 | /// An address without checksum 15 | /// The address with the appended checksum 16 | /// is thrown when an invalid address is provided 17 | public static string AddChecksum(string address) 18 | { 19 | InputValidator.CheckAddress(address); 20 | var addressWithChecksum = address; 21 | addressWithChecksum += CalculateChecksum(address); 22 | return addressWithChecksum; 23 | } 24 | 25 | 26 | /// 27 | /// Removes the checksum from the specified address with checksum 28 | /// 29 | /// The address with checksum or without checksum. 30 | /// the specified address without checksum 31 | /// is thrown when the specified address is not an address with checksum 32 | public static string RemoveChecksum(this string address) 33 | { 34 | if (IsAddressWithChecksum(address)) return GetAddress(address); 35 | 36 | if (IsAddressWithoutChecksum(address)) return address; 37 | 38 | throw new InvalidAddressException(address); 39 | } 40 | 41 | 42 | internal static string GetAddress(string addressWithChecksum) 43 | { 44 | return addressWithChecksum.Substring(0, Constants.AddressLengthWithoutChecksum); 45 | } 46 | 47 | /// 48 | /// Determines whether the specified address with checksum has a valid checksum. 49 | /// 50 | /// The address with checksum. 51 | /// 52 | /// true if the specified address with checksum has a valid checksum [the specified address with checksum]; 53 | /// otherwise, false. 54 | /// 55 | public static bool IsValidChecksum(this string addressWithChecksum) 56 | { 57 | var addressWithoutChecksum = RemoveChecksum(addressWithChecksum); 58 | var adressWithRecalculateChecksum = addressWithoutChecksum + CalculateChecksum(addressWithoutChecksum); 59 | return adressWithRecalculateChecksum.Equals(addressWithChecksum); 60 | } 61 | 62 | 63 | private static bool IsAddressWithChecksum(string addressWithChecksum) 64 | { 65 | return InputValidator.IsAddress(addressWithChecksum) && 66 | addressWithChecksum.Length == Constants.AddressLengthWithChecksum; 67 | } 68 | 69 | private static bool IsAddressWithoutChecksum(string address) 70 | { 71 | return InputValidator.CheckAddress(address) && address.Length == Constants.AddressLengthWithoutChecksum; 72 | } 73 | 74 | private static string CalculateChecksum(string address) 75 | { 76 | // TODO inject curl 77 | ICurl curl = new Kerl(); 78 | curl.Reset(); 79 | curl.Absorb(Converter.ToTrits(address)); 80 | var checksumTrits = new int[Sponge.HashLength]; 81 | curl.Squeeze(checksumTrits); 82 | var checksum = Converter.ToTrytes(checksumTrits); 83 | return checksum.Substring(72, 9); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Utils 2 | { 3 | /// 4 | /// This class defines different constants that are used accros the library 5 | /// 6 | public static class Constants 7 | { 8 | /// 9 | /// This String contains all possible characters of the tryte alphabet 10 | /// 11 | public static readonly string TryteAlphabet = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 12 | 13 | /// 14 | /// The maximum seed length 15 | /// 16 | public static readonly int SeedLengthMax = 81; 17 | 18 | /// 19 | /// This String represents the empty hash consisting of '9' 20 | /// 21 | public static readonly string EmptyHash = 22 | "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; 23 | 24 | /// 25 | /// The length of an address without checksum 26 | /// 27 | public static readonly int AddressLengthWithoutChecksum = 81; 28 | 29 | /// 30 | /// The address length with checksum 31 | /// 32 | public static readonly int AddressLengthWithChecksum = 90; 33 | 34 | /// 35 | /// The length of an message 36 | /// 37 | public static int MessageLength = 2187; 38 | /// 39 | /// 40 | /// 41 | public static int TagLength = 27; 42 | } 43 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/IotaUnitConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Iota.Lib.CSharp.Api.Utils 4 | { 5 | /// 6 | /// This class provides methods to convert Iota to different units 7 | /// 8 | public class IotaUnitConverter 9 | { 10 | /// 11 | /// Convert the iota amount 12 | /// 13 | /// amount 14 | /// the source unit e.g. the unit of amount 15 | /// the target unit 16 | /// the specified amount in the target unit 17 | public static double ConvertUnits(long amount, IotaUnits fromUnit, IotaUnits toUnit) 18 | { 19 | long amountInSource = (long) (amount*Math.Pow(10, (int) fromUnit)); 20 | return ConvertUnits(amountInSource, toUnit); 21 | } 22 | 23 | private static double ConvertUnits(long amount, IotaUnits toUnit) 24 | { 25 | int base10NormalizationExponent = (int) toUnit; 26 | return (amount/Math.Pow(10, base10NormalizationExponent)); 27 | } 28 | 29 | /// 30 | /// Finds the optimal unit to display the specified amount in 31 | /// 32 | /// amount 33 | /// the optimal IotaUnit 34 | public static IotaUnits FindOptimalIotaUnitToDisplay(long amount) 35 | { 36 | int length = (amount).ToString().Length; 37 | 38 | if (amount < 0) 39 | { 40 | // do not count "-" sign 41 | length -= 1; 42 | } 43 | 44 | IotaUnits units = IotaUnits.Iota; 45 | 46 | if (length >= 1 && length <= 3) 47 | { 48 | units = IotaUnits.Iota; 49 | } 50 | else if (length > 3 && length <= 6) 51 | { 52 | units = IotaUnits.Kilo; 53 | } 54 | else if (length > 6 && length <= 9) 55 | { 56 | units = IotaUnits.Mega; 57 | } 58 | else if (length > 9 && length <= 12) 59 | { 60 | units = IotaUnits.Giga; 61 | } 62 | else if (length > 12 && length <= 15) 63 | { 64 | units = IotaUnits.Terra; 65 | } 66 | else if (length > 15 && length <= 18) 67 | { 68 | units = IotaUnits.Peta; 69 | } 70 | return units; 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/IotaUnits.cs: -------------------------------------------------------------------------------- 1 | namespace Iota.Lib.CSharp.Api.Utils 2 | { 3 | /// 4 | /// Iota Units 5 | /// 6 | public enum IotaUnits 7 | { 8 | /// 9 | /// The corresponding value is in iota. Same as 'None' () 10 | /// 11 | Iota = 0, 12 | 13 | /// 14 | /// The corresponding value is in iota. Same as 'Iota' () 15 | /// 16 | None = 0, 17 | 18 | /// 19 | /// 10^3 20 | /// 21 | Kilo = 3, 22 | 23 | /// 24 | /// 10^6 25 | /// 26 | Mega = 6, 27 | 28 | /// 29 | /// 10^9 30 | /// 31 | Giga = 9, 32 | 33 | /// 34 | /// 10^12 35 | /// 36 | Terra = 12, 37 | 38 | /// 39 | /// 10^15 40 | /// 41 | Peta = 15, 42 | } 43 | } -------------------------------------------------------------------------------- /IotaCSharpApi/Api/Utils/TrytesConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Iota.Lib.CSharp.Api.Utils 4 | { 5 | /// 6 | /// This class allows to convert between ASCII and tryte encoded strings 7 | /// 8 | public class TrytesConverter 9 | { 10 | /// 11 | /// Converts the ASCII encoded string to trytes 12 | /// 13 | /// ASCII encoded string 14 | /// tryte encoded string 15 | public static string ToTrytes(string inputString) 16 | { 17 | var trytes = new StringBuilder(); 18 | 19 | foreach (var input in inputString) 20 | { 21 | var asciiValue = input; 22 | 23 | // If not recognizable ASCII character, replace with space 24 | if (asciiValue > 255) asciiValue = ' '; 25 | 26 | trytes.Append(Constants.TryteAlphabet[asciiValue % 27]); 27 | trytes.Append(Constants.TryteAlphabet[asciiValue / 27]); 28 | } 29 | 30 | return trytes.ToString(); 31 | } 32 | 33 | /// 34 | /// Converts the specified tryte encoded String to ASCII 35 | /// 36 | /// tryte encoded string 37 | /// an ASCII encoded string 38 | public static string ToString(string inputTrytes) 39 | { 40 | var builder = new StringBuilder(); 41 | 42 | for (var i = 0; i < inputTrytes.Length; i += 2) 43 | { 44 | // get a trytes pair 45 | 46 | var firstValue = TryteToDecimal(inputTrytes[i]); 47 | var secondValue = TryteToDecimal(inputTrytes[i + 1]); 48 | var decimalValue = firstValue + secondValue * 27; 49 | 50 | builder.Append((char) decimalValue); 51 | } 52 | 53 | return builder.ToString(); 54 | } 55 | 56 | /// 57 | /// Tryte To Decimal, '9' = 0 58 | /// 59 | /// 60 | /// 61 | public static int TryteToDecimal(char tryte) 62 | { 63 | if (tryte == '9') 64 | return 0; 65 | 66 | return tryte - 'A' + 1; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /IotaCSharpApi/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /IotaCSharpApi/IotaCSharpApi.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | CSharp70 -------------------------------------------------------------------------------- /IotaCSharpApi/Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Iota.Lib.CSharp 5 | 0.9.0-beta 6 | sniro 7 | Iota Foundation & Contributors 8 | https://github.com/iotaledger/iota.lib.charp/blob/master/LICENSE 9 | https://github.com/iotaledger/iota.lib.charp 10 | false 11 | Iota C# Library 12 | First Beta Version 13 | Copyright 2017 14 | Iota 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /IotaCSharpApi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Iota.Lib.CSharp")] 10 | [assembly: AssemblyDescription("Iota Library")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Iota Foundation")] 13 | [assembly: AssemblyProduct("Iota.Lib.CSharp")] 14 | [assembly: AssemblyCopyright("Copyright © 2017")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("fc2c2f96-49ea-4046-95bd-3b570bdd1e13")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("0.9.0.*")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /IotaCSharpApi/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Pow/KerlTest.cs: -------------------------------------------------------------------------------- 1 | using Iota.Lib.CSharp.Api.Pow; 2 | using Iota.Lib.CSharp.Api.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Iota.Lib.CSharpTests.Api.Pow 6 | { 7 | [TestClass] 8 | public class KerlTest 9 | { 10 | [TestMethod] 11 | public void ShouldCreateValidHash1() 12 | { 13 | var trits = Converter.ToTrits( 14 | "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"); 15 | var kerl = new Kerl(); 16 | kerl.Reset(); 17 | kerl.Absorb(trits, 0, trits.Length); 18 | var hashTrits = new int[trits.Length]; 19 | kerl.Squeeze(hashTrits, 0, 243); 20 | var hash = Converter.ToTrytes(hashTrits); 21 | Assert.AreEqual(hash, "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW"); 22 | } 23 | 24 | [TestMethod] 25 | public void ShouldCreateValidHash2() 26 | { 27 | var trits = Converter.ToTrits( 28 | "9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH"); 29 | var kerl = new Kerl(); 30 | kerl.Reset(); 31 | kerl.Absorb(trits, 0, trits.Length); 32 | var hashTrits = new int[trits.Length * 2]; 33 | kerl.Squeeze(hashTrits, 0, 243 * 2); 34 | var hash = Converter.ToTrytes(hashTrits); 35 | Assert.AreEqual(hash, 36 | "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); 37 | } 38 | 39 | [TestMethod] 40 | public void ShouldCreateValidHash3() 41 | { 42 | var trits = Converter.ToTrits( 43 | "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); 44 | var kerl = new Kerl(); 45 | kerl.Reset(); 46 | kerl.Absorb(trits, 0, trits.Length); 47 | var hashTrits = new int[trits.Length]; 48 | kerl.Squeeze(hashTrits, 0, 243 * 2); 49 | var hash = Converter.ToTrytes(hashTrits); 50 | Assert.AreEqual(hash, 51 | "LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX"); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Pow/LocalPoWTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Iota.Lib.CSharp.Api; 3 | using Iota.Lib.CSharp.Api.Model; 4 | using Iota.Lib.CSharp.Api.Pow; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Iota.Lib.CSharpTests.Api.Pow 8 | { 9 | [TestClass] 10 | public class LocalPoWTest 11 | { 12 | private static readonly string TEST_SEED1 = 13 | "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; 14 | 15 | private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = 16 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; 17 | 18 | private static readonly string TEST_MESSAGE = "JUSTANOTHERJOTATEST"; 19 | private static readonly string TEST_TAG = "JOTASPAM9999999999999999999"; 20 | private static readonly int MIN_WEIGHT_MAGNITUDE = 14; 21 | private static readonly int DEPTH = 9; 22 | 23 | private IotaApi _iotaClient; 24 | 25 | [TestInitialize] 26 | public void Setup() 27 | { 28 | _iotaClient = new IotaApi("node.iotawallet.info", 14265) 29 | { 30 | LocalPow = new PearlDiverLocalPoW() 31 | }; 32 | } 33 | 34 | [TestMethod] 35 | public void ShouldSendTransfer() 36 | { 37 | var transfers = new List 38 | { 39 | new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG) 40 | }; 41 | var result = _iotaClient.SendTransfer( 42 | TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), 43 | null, null, false, false); 44 | Assert.IsNotNull(result); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Pow/PearlDiverTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Iota.Lib.CSharp.Api.Pow; 4 | using Iota.Lib.CSharp.Api.Utils; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Iota.Lib.CSharpTests.Api.Pow 8 | { 9 | [TestClass] 10 | public class PearlDiverTest 11 | { 12 | 13 | private const int TryteLength = 2673; 14 | private const int MinWeightMagnitude = 9; 15 | private const int NumCores = -1; // use n-1 cores 16 | 17 | private static readonly Random Random = new Random(); 18 | private PearlDiver _pearlDiver; 19 | private int[] _hashTrits; 20 | 21 | [TestInitialize] 22 | public void Setup() 23 | { 24 | _pearlDiver = new PearlDiver(); 25 | _hashTrits = new int[Sponge.HashLength]; 26 | } 27 | 28 | 29 | [TestMethod] 30 | public void TestRandomTryteHash() 31 | { 32 | string testTrytes = GetRandomTrytes(); 33 | 34 | string hash = GetHashFor(testTrytes); 35 | 36 | string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); 37 | 38 | bool success = InputValidator.IsNinesTrytes(subHash,subHash.Length); 39 | if (!success) 40 | { 41 | Console.WriteLine(testTrytes); 42 | } 43 | 44 | Assert.IsTrue(success, "The hash should have n nines"); 45 | } 46 | 47 | [TestMethod] 48 | [Ignore] 49 | public void TestRandomTryteHash100() 50 | { 51 | for (int i = 0; i < 100; i++) 52 | { 53 | string testTrytes = GetRandomTrytes(); 54 | 55 | string hash = GetHashFor(testTrytes); 56 | 57 | string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); 58 | 59 | bool success = InputValidator.IsNinesTrytes(subHash, subHash.Length); 60 | if (!success) 61 | { 62 | Console.WriteLine(testTrytes); 63 | } 64 | 65 | Assert.IsTrue(success, "The hash should have n nines"); 66 | } 67 | } 68 | 69 | private string GetRandomTrytes() 70 | { 71 | var trytes = new StringBuilder(); 72 | 73 | for (int i = 0; i < TryteLength; i++) 74 | { 75 | trytes.Append(Constants.TryteAlphabet[Random.Next(27)]); 76 | } 77 | 78 | return trytes.ToString(); 79 | } 80 | 81 | private string GetHashFor(string trytes) 82 | { 83 | Sponge curl = new Curl(CurlMode.CurlP81); 84 | int[] myTrits = Converter.ToTrits(trytes); 85 | 86 | bool result = _pearlDiver.Search(myTrits, MinWeightMagnitude, NumCores); 87 | 88 | Assert.IsTrue(result,"Search Failed"); 89 | 90 | curl.Absorb(myTrits, 0, myTrits.Length); 91 | curl.Squeeze(_hashTrits, 0, Sponge.HashLength); 92 | curl.Reset(); 93 | 94 | return Converter.ToTrytes(_hashTrits); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Utils/BigIntConverterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Iota.Lib.CSharp.Api.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using Org.BouncyCastle.Math; 5 | 6 | namespace Iota.Lib.CSharpTests.Api.Utils 7 | { 8 | [TestClass] 9 | public class BigIntConverterTest 10 | { 11 | private static readonly Random Random = new Random(); 12 | // trits<->BigInteger<->byte 13 | 14 | [TestMethod] 15 | public void TestTritsAndBigInt() 16 | { 17 | int[] inputTrits = new int[243]; 18 | for (int i = 0; i < inputTrits.Length; i++) 19 | { 20 | inputTrits[i] = Random.Next(3) - 1; 21 | } 22 | 23 | var bigInt = BigIntConverter.BigIntFromTrits(inputTrits, 0, inputTrits.Length); 24 | 25 | int[] outputTrits = new int[inputTrits.Length]; 26 | BigIntConverter.TritsFromBigInt(bigInt, outputTrits, 0, outputTrits.Length); 27 | 28 | for (int i = 0; i < inputTrits.Length; i++) 29 | { 30 | Assert.AreEqual(inputTrits[i], outputTrits[i]); 31 | } 32 | } 33 | 34 | [TestMethod] 35 | public void TestBigIntAndByte() 36 | { 37 | byte[] bytes = new byte[48]; 38 | BigInteger bigInt0 = new BigInteger("-123456"); 39 | 40 | BigIntConverter.BytesFromBigInt(bigInt0, bytes, 0, bytes.Length); 41 | var bigInt1 = BigIntConverter.BigIntFromBytes(bytes, 0, bytes.Length); 42 | 43 | Assert.AreEqual(bigInt0,bigInt1); 44 | } 45 | 46 | [TestMethod] 47 | public void TestFixedBigInt() 48 | { 49 | int[] inputTrits = new int[243]; 50 | int[] outputTrits = new int[243]; 51 | byte[] bytes = new byte[384/8]; 52 | 53 | for (int i = 0; i < inputTrits.Length; i++) 54 | { 55 | inputTrits[i] = Random.Next(3) - 1; 56 | } 57 | 58 | inputTrits[inputTrits.Length - 1] = 0; 59 | FixedBigIntConverter.FromTritsToBytes(inputTrits,bytes); 60 | FixedBigIntConverter.FromBytesToTrits(bytes,outputTrits); 61 | outputTrits[outputTrits.Length - 1] = 0; 62 | 63 | for (int i = 0; i < inputTrits.Length; i++) 64 | { 65 | Assert.AreEqual(inputTrits[i], outputTrits[i]); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Utils/ChecksumTest.cs: -------------------------------------------------------------------------------- 1 | using Iota.Lib.CSharp.Api.Utils; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Iota.Lib.CSharpTests.Api.Utils 5 | { 6 | [TestClass] 7 | public class ChecksumTest 8 | { 9 | private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM = 10 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; 11 | 12 | private static readonly string TEST_ADDRESS_WITH_CHECKSUM = 13 | "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; 14 | 15 | [TestMethod] 16 | public void ShouldAddChecksum() 17 | { 18 | Assert.AreEqual(Checksum.AddChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); 19 | } 20 | 21 | [TestMethod] 22 | public void ShouldRemoveChecksum() 23 | { 24 | Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.RemoveChecksum(), TEST_ADDRESS_WITHOUT_CHECKSUM); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldIsValidChecksum() 29 | { 30 | Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.IsValidChecksum(), true); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Utils/IotaUnitConverterTests.cs: -------------------------------------------------------------------------------- 1 | using Iota.Lib.CSharp.Api.Utils; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Iota.Lib.CSharpTests.Api.Utils 5 | { 6 | [TestClass] 7 | public class IotaUnitConverterTest 8 | { 9 | [TestMethod] 10 | public void ShouldConvertUnitItoKi() 11 | { 12 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Iota, IotaUnits.Kilo), 1); 13 | } 14 | 15 | [TestMethod] 16 | public void ShouldConvertUnitKiToMi() 17 | { 18 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Kilo, IotaUnits.Mega), 1); 19 | } 20 | 21 | [TestMethod] 22 | public void ShouldConvertUnitMiToGi() 23 | { 24 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Mega, IotaUnits.Giga), 1); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldConvertUnitGiToTi() 29 | { 30 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Giga, IotaUnits.Terra), 1); 31 | } 32 | 33 | [TestMethod] 34 | public void ShouldConvertUnitTiToPi() 35 | { 36 | Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Terra, IotaUnits.Peta), 1); 37 | } 38 | 39 | [TestMethod] 40 | public void ShouldFindOptimizeUnitToDisplay() 41 | { 42 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1), IotaUnits.Iota); 43 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000), IotaUnits.Kilo); 44 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000), IotaUnits.Mega); 45 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000), IotaUnits.Giga); 46 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000L), IotaUnits.Terra); 47 | Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000000L), IotaUnits.Peta); 48 | } 49 | 50 | /*[TestMethod] 51 | public void shouldConvertRawIotaAmountToDisplayText() 52 | { 53 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1, false), "1 i"); 54 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000, false), "1 Ki"); 55 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000, false), "1 Mi"); 56 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000, false), "1 Gi"); 57 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L, false), "1 Ti"); 58 | Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L, false), "1 Pi"); 59 | }*/ 60 | } 61 | } -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Utils/MultisigTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Iota.Lib.CSharp.Api; 4 | using Iota.Lib.CSharp.Api.Model; 5 | using Iota.Lib.CSharp.Api.Pow; 6 | using Iota.Lib.CSharp.Api.Utils; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace Iota.Lib.CSharpTests.Api.Utils 10 | { 11 | [TestClass] 12 | public class MultisigTest 13 | { 14 | private const string TestSeed1 = "ABCDFG"; 15 | private const string TestSeed2 = "FDSAG"; 16 | 17 | private const string RemainderAddress = 18 | "NZRALDYNVGJWUVLKDWFKJVNYLWQGCWYCURJIIZRLJIKSAIVZSGEYKTZRDBGJLOA9AWYJQB9IPWRAKUC9FBDRZJZXZG"; 19 | 20 | private const string ReceiveAddress = 21 | "ZGHXPZYDKXPEOSQTAQOIXEEI9K9YKFKCWKYYTYAUWXK9QZAVMJXWAIZABOXHHNNBJIEBEUQRTBWGLYMTX"; 22 | 23 | private const string TestTag = "JOTASPAM9999999999999999999"; 24 | 25 | 26 | private IotaApi _iotaClient; 27 | 28 | [TestInitialize] 29 | public void CreateApiClientInstance() 30 | { 31 | _iotaClient = new IotaApi("node.iotawallet.info", 14265); 32 | } 33 | 34 | [TestMethod] 35 | public void BasicMultiSigTest() 36 | { 37 | Multisig ms = new Multisig(); 38 | 39 | // First co-signer uses security level 3 and index 0 for the private key 40 | string digestOne = ms.GetDigest(TestSeed1, 3, 0); 41 | 42 | // We initiate the multisig address generation by absorbing the key digest 43 | ms.AddAddressDigest(new[] {digestOne}); 44 | 45 | // Second cosigner also uses security level 3 and index 0 for the private key 46 | string digestTwo = ms.GetDigest(TestSeed2, 3, 0); 47 | 48 | // Add the multisig by absorbing the second cosigners key digest 49 | ms.AddAddressDigest(new[] {digestTwo}); 50 | 51 | // finally we generate the multisig address itself 52 | string multiSigAddress = ms.FinalizeAddress(); 53 | 54 | Console.WriteLine("MultisigAddress = " + multiSigAddress); 55 | 56 | 57 | bool isValidMultisigAddress = ms.ValidateAddress(multiSigAddress, 58 | new[] {Converter.ToTrits(digestOne), Converter.ToTrits(digestTwo)}); 59 | 60 | Console.WriteLine("Is a valid multisig address " + isValidMultisigAddress); 61 | 62 | Assert.IsTrue(isValidMultisigAddress, "Address is not a valid multisigAddress"); 63 | 64 | List transfers = new List 65 | { 66 | new Transfer(ReceiveAddress, 999, "", TestTag) 67 | }; 68 | 69 | List trxs = 70 | _iotaClient.InitiateTransfer(6, multiSigAddress, RemainderAddress, transfers, true); 71 | 72 | Bundle bundle = new Bundle(trxs, trxs.Count); 73 | 74 | bundle = ms.AddSignature(bundle, multiSigAddress, ms.GetKey(TestSeed1, 0, 3)); 75 | 76 | bundle = ms.AddSignature(bundle, multiSigAddress, ms.GetKey(TestSeed2, 0, 3)); 77 | 78 | 79 | Signing sgn = new Signing(new Kerl()); 80 | 81 | bool isValidSignature = sgn.ValidateSignatures(bundle, multiSigAddress); 82 | Console.WriteLine("Result of multi-signature validation is " + isValidSignature); 83 | Assert.IsTrue(isValidSignature, "MultiSignature not valid"); 84 | 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Api/Utils/TrytesConverterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Iota.Lib.CSharp.Api.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Iota.Lib.CSharpTests.Api.Utils 7 | { 8 | [TestClass] 9 | public class TrytesConverterTest 10 | { 11 | private static readonly Random Random = new Random(); 12 | 13 | [TestMethod] 14 | public void ShouldConvertStringToTrytes() 15 | { 16 | Assert.AreEqual("IC", TrytesConverter.ToTrytes("Z")); 17 | Assert.AreEqual(TrytesConverter.ToTrytes("JOTA JOTA"), "TBYBCCKBEATBYBCCKB"); 18 | } 19 | 20 | [TestMethod] 21 | public void ShouldConvertTrytesToString() 22 | { 23 | Assert.AreEqual("Z", TrytesConverter.ToString("IC")); 24 | Assert.AreEqual(TrytesConverter.ToString("TBYBCCKBEATBYBCCKB"), "JOTA JOTA"); 25 | } 26 | 27 | [TestMethod] 28 | public void ShouldConvertBackAndForth() 29 | { 30 | var str = RandomString(1000); 31 | var back = TrytesConverter.ToString(TrytesConverter.ToTrytes(str)); 32 | Assert.AreEqual(str, back); 33 | } 34 | 35 | public static string RandomString(int length) 36 | { 37 | const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 38 | return new string(Enumerable.Repeat(chars, length) 39 | .Select(s => s[Random.Next(s.Length)]).ToArray()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("IotaCSharpApiUnitTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IotaCSharpApiUnitTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("fae71c0d-c373-4401-b9de-bc3dc1d4e435")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | 38 | [assembly: AssemblyVersion("1.0.0.0")] 39 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /IotaCSharpApiUnitTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/928xuq2obg1itui7/branch/master?svg=true)](https://ci.appveyor.com/project/adrianziser/iota-lib-csharp/branch/master) 2 | 3 | ## Introduction 4 | 5 | The Iota.Lib.CSharp library implements the [[Core API calls]](https://iota.readme.io/docs/getnodeinfo) as well as the [[proposed calls]](https://github.com/iotaledger/wiki/blob/master/api-proposal.md). 6 | 7 | It allows to connect easily to a local or a remote [[IOTA node]](https://iota.readme.io/docs/syncing-to-the-network) using C#. 8 | 9 | * **Latest release:** 0.9.0-beta 10 | * **Compatibility:** fully compatible with IOTA IRI v1.2.4 11 | * **License:** Apache License 2.0 12 | 13 | ### Technologies & dependencies 14 | 15 | The Iota.Lib.CSharp library has been designed to be used with .Net 4.0+. 16 | 17 | Core dependencies: 18 | * RestSharp 4.0.30319 [[link]](https://github.com/restsharp/RestSharp) 19 | * Json.NET 9.0.0.0 [[link]](https://github.com/JamesNK/Newtonsoft.Json) 20 | 21 | ### Getting started 22 | 23 | Connect to your node is quite straightforward: it requires only 2 lines of code. For example, in order to fetch the Node Info: 24 | 25 | ```cs 26 | IotaApi iotaApi = new IotaApi("node.iotawallet.info", 14265); 27 | GetNodeInfoResponse nodeInfo = iotaApi.GetNodeInfo(); 28 | ``` 29 | 30 | You can easily add the library to your Visual Studio project using the NuGet package manager or in the Package Manager Console with this command: 31 | 32 | ```PowerShell 33 | Install-Package Iota.Lib.CSharp -Pre 34 | ``` 35 | 36 | ### Documentation 37 | 38 | Please refer to the [github wiki](https://github.com/iotaledger/iota.lib.csharp/wiki) for the library documentation. 39 | 40 | ### Warning 41 | - This is pre-release software! 42 | - There may be performance and stability issues. 43 | - You may loose all your money :) 44 | - Please report any issues using the Issue Tracker 45 | 46 | ### What is missing 47 | - Multisig support -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | image: Visual Studio 2017 3 | before_build: 4 | - nuget restore 5 | build: 6 | project: IotaApi.sln 7 | verbosity: minimal --------------------------------------------------------------------------------