Skip to content

Commit 14e6676

Browse files
authored
Merge pull request #156 from IOTA-NET/152-allow-bech32-encoding-and-decoding-to-ed22519
Bech32 encoding decoding
2 parents 2df6715 + 29698e4 commit 14e6676

File tree

3 files changed

+405
-1
lines changed

3 files changed

+405
-1
lines changed

csharp/IotaWalletNet/IotaWalletNet.Domain/Common/Extensions/StringExtensions.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
using Blake2Fast;
1+
using Bech32;
2+
using Blake2Fast;
3+
using IotaWalletNet.Domain.Common.Models.Address;
4+
using IotaWalletNet.Domain.Common.Models.Coin;
5+
using IotaWalletNet.Domain.Common.Models.Network;
6+
using System.Buffers.Text;
27
using System.Text;
38

49
namespace IotaWalletNet.Domain.Common.Extensions
@@ -42,5 +47,35 @@ public static string ComputeBlake2bHash(this string hexEncoded)
4247

4348
return "0x" + Convert.ToHexString(hash);
4449
}
50+
51+
public static string EncodeEd25519HashIntoBech32(this string blake2bHashOfEd25519, NetworkType networkType, TypeOfCoin typeOfCoin)
52+
{
53+
blake2bHashOfEd25519 = blake2bHashOfEd25519.Trim().ToLower();
54+
if (blake2bHashOfEd25519.StartsWith("0x"))
55+
blake2bHashOfEd25519 = blake2bHashOfEd25519.Substring(2); // remove the 0x of a hexstring eg 0x1337
56+
57+
string hrp = HumanReadablePart.GetHumanReadablePart(networkType, typeOfCoin);
58+
const string ED25519_TYPE = "00";
59+
blake2bHashOfEd25519 = ED25519_TYPE + blake2bHashOfEd25519;
60+
61+
string bech32 = Bech32Engine.Encode(hrp, Convert.FromHexString(blake2bHashOfEd25519));
62+
63+
const string HRP_CONSTANT = "1";
64+
65+
return $"{hrp}{HRP_CONSTANT}{bech32}";
66+
}
67+
68+
public static string DecodeBech32IntoEd25519Hash(this string bech32, NetworkType networkType, TypeOfCoin typeOfCoin)
69+
{
70+
bech32 = bech32.Trim().ToLower();
71+
72+
string hrp = HumanReadablePart.GetHumanReadablePart(networkType, typeOfCoin);
73+
74+
string bech32OfInterest = bech32.Substring(4); //eg remove iota1 or smr1 or atoi1 or rms1
75+
76+
byte[] decoded = Bech32Engine.Decode(bech32OfInterest, hrp);
77+
78+
return "0x" + Convert.ToHexString(decoded);
79+
}
4580
}
4681
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using IotaWalletNet.Domain.Common.Models.Coin;
2+
using IotaWalletNet.Domain.Common.Models.Network;
3+
4+
namespace IotaWalletNet.Domain.Common.Models.Address
5+
{
6+
/// <summary>
7+
///
8+
/// Bech32 for human-readable encoding
9+
/// The human-readable encoding of the address is Bech32(as described in BIP-0173). A Bech32 string is at most 90 characters long and consists of:
10+
11+
/// The human-readable part(HRP), which conveys the IOTA protocol and distinguishes between Mainnet(the IOTA token) and Testnet(testing version):
12+
/// iota is the human-readable part for Mainnet addresses
13+
/// atoi is the human-readable part for Testnet addresses
14+
/// The separator, which is always 1.
15+
/// The data part, which consists of the Base32 encoded serialized address and the 6-character checksum.
16+
/// </summary>
17+
public static class HumanReadablePart
18+
{
19+
public enum HRP
20+
{
21+
iota,
22+
atoi,
23+
smr,
24+
rms
25+
}
26+
27+
private static IReadOnlyDictionary<TypeOfCoin, string> MainnetToHrp = new Dictionary<TypeOfCoin, string>()
28+
{
29+
{ TypeOfCoin.Iota, HRP.iota.ToString() },
30+
{ TypeOfCoin.Shimmer, HRP.smr.ToString() },
31+
32+
};
33+
private static IReadOnlyDictionary<TypeOfCoin, string> TestnetToHrp = new Dictionary<TypeOfCoin, string>()
34+
{
35+
{ TypeOfCoin.Iota, HRP.atoi.ToString() },
36+
{ TypeOfCoin.Shimmer, HRP.rms.ToString() },
37+
38+
};
39+
40+
public static string GetHumanReadablePart(NetworkType networkType, TypeOfCoin typeOfCoin)
41+
{
42+
if (networkType == NetworkType.Mainnet)
43+
return MainnetToHrp[typeOfCoin];
44+
else
45+
return TestnetToHrp[typeOfCoin];
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)