Skip to content

Commit

Permalink
v0.18.0: TonRecipes.TelegramNumbers and TonRecipes.TelegramUsernames
Browse files Browse the repository at this point in the history
  • Loading branch information
justdmitry committed Jun 6, 2023
1 parent 0b34aa3 commit 2fac981
Show file tree
Hide file tree
Showing 9 changed files with 378 additions and 159 deletions.
9 changes: 8 additions & 1 deletion TonLibDotNet.Demo/Samples/Recipes/TelemintGetAllInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ public async Task Run(bool inMainnet)

var domain = "dolboeb.t.me";

var ti = await TonRecipes.Telemint.GetAllInfoByName(tonClient, domain);
var ti = await TonRecipes.TelegramUsernames.GetAllInfoByName(tonClient, domain);

// Output as JSON because I'm too lazy to write separate lines for each field.
logger.LogInformation(
"Info about '{Domain}':\r\n{Json}",
domain,
JsonSerializer.Serialize(ti, new JsonSerializerOptions() { WriteIndented = true }));

var number = "+888 0000 8888";
ti = await TonRecipes.TelegramNumbers.GetAllInfoByName(tonClient, number);
logger.LogInformation(
"Info about '{Domain}':\r\n{Json}",
number,
JsonSerializer.Serialize(ti, new JsonSerializerOptions() { WriteIndented = true }));
}
}
}
93 changes: 93 additions & 0 deletions TonLibDotNet.Tests/Recipes/TelegramNumbersRecipes_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
namespace TonLibDotNet.Recipes
{
[Collection(TonClientMainnetCollection.Definition)]
public class TelegramNumbersRecipes_Tests
{
private readonly Func<Task<ITonClient>> getTonClient;

private readonly TelegramNumbersRecipes instance = TelegramNumbersRecipes.Instance;

private const string ValidName = "88800008888";
private const string ValidNameAddress = "EQByytVzsVlfuuIALs0b6X_0SrXHXNqBRXPf4S1P6Nm6ZNF4";

public TelegramNumbersRecipes_Tests(TonClientMainnetFixture fixture)
{
getTonClient = fixture.GetTonClient;
}

[Theory]
[InlineData("88800008888", "88800008888")]
[InlineData("+888 0000 8888", "88800008888")]
[InlineData("+888-0000-8888", "88800008888")]
[InlineData("+888 (0000) 8888", "88800008888")]
[InlineData("888 8888 8888 8888", "888888888888888")]
public void NormalizeNameWorks(string name, string expected)
{
Assert.True(instance.TryNormalizeName(name, out var normalizedName));
Assert.Equal(expected, normalizedName);
}

[Fact]
public void NormalizeNameRejectsEmpty()
{
Assert.Throws<ArgumentNullException>(() => instance.TryNormalizeName(null, out _));
Assert.Throws<ArgumentNullException>(() => instance.TryNormalizeName(string.Empty, out _));
}

[Theory]
[InlineData("888~00008888")]
[InlineData("888a00008888")]
[InlineData("77700008888")]
public void NormalizeNameRejectsInvalid(string name)
{
Assert.False(instance.TryNormalizeName(name, out _));
}

[Theory]
[InlineData(ValidName)]
public async Task ResolveMinted(string name)
{
var tonClient = await getTonClient();

var adr = await instance.GetNftAddress(tonClient, name);
Assert.Equal(ValidNameAddress, adr);
}

[Fact]
public async Task ResolveNotMinted()
{
var tonClient = await getTonClient();

// Does not exist as NFT at time of writing this test
var adr = await instance.GetNftAddress(tonClient, "888 8888 8888 8888");

// How to get expected value?
// Replace with Assert.Equal if you know how.
Assert.False(string.IsNullOrEmpty(adr));
}

[Fact]
public async Task GetTokenNameWorks()
{
var tonClient = await getTonClient();
var dn = await instance.GetTokenName(tonClient, ValidNameAddress);
Assert.Equal(ValidName, dn);
}

[Fact]
public async Task GetAllInfoWorks()
{
var tonClient = await getTonClient();
var ti = await instance.GetAllInfo(tonClient, ValidNameAddress);
Assert.NotNull(ti);
}

[Fact]
public async Task GetAllInfoByNameWorks()
{
var tonClient = await getTonClient();
var ti = await instance.GetAllInfoByName(tonClient, ValidName);
Assert.NotNull(ti);
}
}
}
103 changes: 103 additions & 0 deletions TonLibDotNet.Tests/Recipes/TelegramUsernamesRecipes_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
namespace TonLibDotNet.Recipes
{
[Collection(TonClientMainnetCollection.Definition)]
public class TelegramUsernamesRecipes_Tests
{
private readonly Func<Task<ITonClient>> getTonClient;

private readonly TelegramUsernamesRecipes instance = TelegramUsernamesRecipes.Instance;

private const string ValidNameFull = "welcome.t.me";
private const string ValidNameShort = "welcome";
private const string ValidNameAddress = "EQAngajSUhC0DfUN1OHp33-6w06Mt33fjm4KcwzMU3bGXx_E";

public TelegramUsernamesRecipes_Tests(TonClientMainnetFixture fixture)
{
getTonClient = fixture.GetTonClient;
}

[Theory]
[InlineData("wElCoMe.t.me", "welcome")]
[InlineData("wELCOME.T.ME.", "welcome")]
[InlineData("welcome", "welcome")]
[InlineData("welcome.", "welcome")]
[InlineData("not-yet-minted-name.t.me", "not-yet-minted-name")]
public void NormalizeNameWorks(string name, string expected)
{
Assert.True(instance.TryNormalizeName(name, out var normalizedName));
Assert.Equal(expected, normalizedName);
}

[Fact]
public void NormalizeNameRejectsEmpty()
{
Assert.Throws<ArgumentNullException>(() => instance.TryNormalizeName(null, out _));
Assert.Throws<ArgumentNullException>(() => instance.TryNormalizeName(string.Empty, out _));
}

[Theory]
[InlineData("subdomain.domain.t.me")]
[InlineData("subdomain.domain")]
[InlineData("welcome.ton")]
public void NormalizeNameRejectsInvalid(string name)
{
Assert.False(instance.TryNormalizeName(name, out _));
}

[Theory]
[InlineData(ValidNameFull)]
[InlineData(ValidNameShort)]
public async Task ResolveMinted(string name)
{
var tonClient = await getTonClient();

var adr = await instance.GetNftAddress(tonClient, name);
Assert.Equal(ValidNameAddress, adr);
}

[Fact]
public async Task ResolveNotMinted()
{
var tonClient = await getTonClient();

// Does not exist as NFT at time of writing this test
var adr = await instance.GetNftAddress(tonClient, "not-yet-minted-name.t.me");

// How to get expected value?
// Replace with Assert.Equal if you know how.
Assert.False(string.IsNullOrEmpty(adr));
}

[Fact]
public async Task GetFullDomainWorks()
{
var tonClient = await getTonClient();
var dn = await instance.GetFullDomain(tonClient, ValidNameAddress);
Assert.Equal(ValidNameFull, dn);
}

[Fact]
public async Task GetTokenNameWorks()
{
var tonClient = await getTonClient();
var dn = await instance.GetTokenName(tonClient, ValidNameAddress);
Assert.Equal(ValidNameShort, dn);
}

[Fact]
public async Task GetAllInfoWorks()
{
var tonClient = await getTonClient();
var ti = await instance.GetAllInfo(tonClient, ValidNameAddress);
Assert.NotNull(ti);
}

[Fact]
public async Task GetAllInfoByNameWorks()
{
var tonClient = await getTonClient();
var ti = await instance.GetAllInfoByName(tonClient, ValidNameFull);
Assert.NotNull(ti);
}
}
}
94 changes: 0 additions & 94 deletions TonLibDotNet.Tests/Recipes/TelemintRecipes_Tests.cs

This file was deleted.

71 changes: 71 additions & 0 deletions TonLibDotNet/Recipes/TelegramNumbersRecipes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Diagnostics.CodeAnalysis;

namespace TonLibDotNet.Recipes
{
/// <inheritdoc />
public class TelegramNumbersRecipes : TelemintRecipes
{
public static readonly TelegramNumbersRecipes Instance = new();

public override string CollectionAddress => "EQAOQdwdw8kGftJCSFgOErM1mBjYPe4DBPq8-AhF6vr9si5N";

/// <inheritdoc />
/// <remarks>
/// <para>Valid numers starts with '888' (or '+888') and must contain up to 16 digits, and optional delimiters (<b>+</b>, <b>(</b>, <b>)</b> and <b>-</b>).</para>
/// </remarks>
/// <exception cref="ArgumentNullException">Provided <paramref name="name"/> is null or empty or whitespace.</exception>
public override bool TryNormalizeName(string name, [NotNullWhen(true)] out string normalizedName)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}

normalizedName = string.Empty;

const int maxLen = 16; // currently numbers contain 7 or 11 digits, but will add a bit for future
var len = 0;
Span<char> chars = stackalloc char[maxLen];

foreach (var ch in name)
{
switch (ch)
{
case '0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9':
if (len >= maxLen)
{
return false;
}

chars[len++] = ch;
continue;
case ' ' or '+' or '-' or '(' or ')':
continue;
default:
return false;
}
}

if (!chars.StartsWith("888"))
{
return false;
}

normalizedName = chars[..len].ToString();
return true;
}

/// <summary>
/// ⚠ Original 'get_full_domain' method had been excluded from contract code.
/// </summary>
/// <remarks>
/// Will always throw <see cref="NotImplementedException"/>.
/// </remarks>
/// <exception cref="NotImplementedException">Always.</exception>
[Obsolete("Original 'get_full_domain' method had been excluded from contract code.")]
public new Task<string> GetFullDomain(ITonClient tonClient, string nftAddress)
{
throw new NotImplementedException("Original 'get_full_domain' method had been excluded from contract code.");
}
}
}
Loading

0 comments on commit 2fac981

Please sign in to comment.