Skip to content

Commit 1542e63

Browse files
GET account-meta/:account (#18)
* Implemented GET account-meta/:account into the `XummMiscClient`. * Added Account Meta Unit Tests * Added the Account Meta retrieval example to the Server App.
1 parent dc203b8 commit 1542e63

File tree

12 files changed

+309
-5
lines changed

12 files changed

+309
-5
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
@page "/account-meta"
2+
@using XUMM.NET.SDK.Clients.Interfaces
3+
@using XUMM.NET.SDK.Extensions
4+
@using XUMM.NET.SDK.Models.Misc
5+
@using XUMM.NET.ServerApp.Extensions
6+
7+
@inject IOptions<XrplConfig> Config
8+
@inject IXummMiscClient _miscClient
9+
10+
<PageTitle>Account Meta</PageTitle>
11+
12+
<ResponseAlertBox @ref="_responseAlertBox"></ResponseAlertBox>
13+
14+
<h1>Account Meta</h1>
15+
16+
<div class="row align-items-start">
17+
<div class="col-md-6">
18+
<div class="row">
19+
<div class="mb-3">
20+
<label for="account" class="form-label">Account</label>
21+
<input id="account" type="text" class="form-control" placeholder="Account address, eg. @Config.Value.Account" aria-label="Account" aria-describedby="basic-addon2" @bind="_account">
22+
</div>
23+
<div class="btn-group mb-3" role="group">
24+
<button class="btn btn-primary" type="button" @onclick="GetAccountMetaAsync">Fetch Account Meta</button>
25+
</div>
26+
</div>
27+
28+
@if (_accountMeta != null)
29+
{
30+
<div class="row">
31+
<div class="mb-3">
32+
<h2>Account Meta</h2>
33+
<dl class="row">
34+
<dt class="col-6">Account</dt>
35+
<dd class="col-6 text-break">@_accountMeta.Account</dd>
36+
<dt class="col-6">KYC Approved</dt>
37+
<dd class="col-6 text-break">@(_accountMeta.KycApproved ? "Yes" : "No")</dd>
38+
<dt class="col-6">XUMM Pro</dt>
39+
<dd class="col-6 text-break">@(_accountMeta.XummPro ? "Yes" : "No")</dd>
40+
</dl>
41+
42+
@if (_accountMeta.XummProfile != null)
43+
{
44+
<h2>XUMM Profile</h2>
45+
<dl class="row">
46+
<dt class="col-6">Account Alias</dt>
47+
<dd class="col-6 text-break">@_accountMeta.XummProfile.AccountAlias</dd>
48+
<dt class="col-6">Owner Alias</dt>
49+
<dd class="col-6 text-break">@_accountMeta.XummProfile.OwnerAlias</dd>
50+
</dl>
51+
}
52+
53+
@if (_accountMeta.GlobaliD?.ProfileUrl != null && _accountMeta.GlobaliD?.Linked != null)
54+
{
55+
<h2>GlobaliD</h2>
56+
<dl class="row">
57+
<dt class="col-6">Profile URL</dt>
58+
<dd class="col-6 text-break"><a href="@_accountMeta.GlobaliD.ProfileUrl" target="_blank">@_accountMeta.GlobaliD.ProfileUrl</a></dd>
59+
<dt class="col-6">Linked</dt>
60+
<dd class="col-6 text-break">@_accountMeta.GlobaliD.Linked</dd>
61+
</dl>
62+
}
63+
64+
@if (_accountMeta.ThirdPartyProfiles.Any())
65+
{
66+
<h2>Third Party Profiles</h2>
67+
<table class="table">
68+
<thead>
69+
<tr>
70+
<th scope="col">Source</th>
71+
<th scope="col">Account Alias</th>
72+
</tr>
73+
</thead>
74+
<tbody>
75+
@foreach (var thirdPartyProfile in _accountMeta.ThirdPartyProfiles.OrderBy(x => x.Source))
76+
{
77+
<tr>
78+
<th scope="row">@thirdPartyProfile.Source</th>
79+
<td>@thirdPartyProfile.AccountAlias</td>
80+
</tr>
81+
}
82+
</tbody>
83+
</table>
84+
}
85+
</div>
86+
</div>
87+
}
88+
</div>
89+
<div class="col-md-6 text-center">
90+
@if (_accountMeta?.Avatar != null)
91+
{
92+
<div class="input-group mb-3">
93+
<figure class="figure">
94+
<img src="@_accountMeta.Avatar" class="figure-img img-fluid rounded" alt="Avatar of account @_account">
95+
<figcaption class="figure-caption text-break">@_accountMeta.Avatar</figcaption>
96+
</figure>
97+
</div>
98+
}
99+
</div>
100+
</div>
101+
@code {
102+
private ResponseAlertBox _responseAlertBox = default!;
103+
private string _account = default!;
104+
private XummAccountMetaResponse? _accountMeta;
105+
106+
private async Task GetAccountMetaAsync()
107+
{
108+
if (!_account.IsAccountAddress())
109+
{
110+
_account = Config.Value.Account;
111+
}
112+
113+
_accountMeta = await _responseAlertBox.GetResponseAndSetAlertAsync(() => _miscClient.AccountMetaAsync(_account));
114+
_responseAlertBox.SetAlert("Account Meta", _accountMeta != null);
115+
}
116+
}

examples/XUMM.Net.ServerApp/Shared/NavMenu.razor

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
<NavLink class="nav-link ps-4" href="/user-tokens">
3939
<span class="oi oi-key" aria-hidden="true"></span> User Tokens
4040
</NavLink>
41+
<NavLink class="nav-link ps-4" href="/account-meta">
42+
<span class="oi oi-copywriting" aria-hidden="true"></span> Account Meta
43+
</NavLink>
4144
<NavLink class="nav-link ps-4" href="/avatar">
4245
<span class="oi oi-image" aria-hidden="true"></span> Avatar
4346
</NavLink>

src/XUMM.NET.SDK.Tests/Clients/XummMiscClientTests.cs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ public async Task GetTransactionAsync_WithValidTxHash_ShouldContainTxHashInReque
192192
_httpMessageHandlerMock.SetFixtureMessage(HttpStatusCode.OK, "xrpltx");
193193

194194
// Act
195-
var result = await _subject.GetTransactionAsync(txHash);
195+
_ = await _subject.GetTransactionAsync(txHash);
196196

197197
// Assert
198198
_httpMessageHandlerMock.AssertRequestUri(HttpMethod.Get, $"/xrpl-tx/{txHash}");
@@ -234,7 +234,7 @@ public async Task VerifyUserTokenAsync_WithValidUserToken_ShouldContainUserToken
234234
_httpMessageHandlerMock.SetFixtureMessage(HttpStatusCode.OK, "user-token");
235235

236236
// Act
237-
var result = await _subject.VerifyUserTokenAsync(userToken);
237+
_ = await _subject.VerifyUserTokenAsync(userToken);
238238

239239
// Assert
240240
_httpMessageHandlerMock.AssertRequestUri(HttpMethod.Get, $"/user-token/{userToken}");
@@ -283,6 +283,46 @@ public void VerifyUserTokensAsync_WithoutUserTokens_ShouldThrowExceptionAsync()
283283
Assert.That(ex!.Message, Is.EqualTo("Value cannot be null or empty (Parameter 'userTokens')"));
284284
}
285285

286+
[Test]
287+
[TestCase("rBLomsmaSJ1ttBmS3WPmPpWLAUDKFwiF9Q")]
288+
public async Task GetAccountMetaAsync_WithValidAccount_ShouldReturnAccountMetaAsync(string account)
289+
{
290+
// Arrange
291+
_httpMessageHandlerMock.SetFixtureMessage(HttpStatusCode.OK, "account-meta");
292+
293+
// Act
294+
var result = await _subject.AccountMetaAsync(account);
295+
296+
// Assert
297+
AssertExtensions.AreEqual(MiscFixtures.XummAccountMeta, result);
298+
}
299+
300+
[Test]
301+
[TestCase("rBLomsmaSJ1ttBmS3WPmPpWLAUDKFwiF9Q")]
302+
public async Task GetAccountMetaAsync_WithValidAccount_ShouldContainAccountInRequestUriAsync(string account)
303+
{
304+
// Arrange
305+
_httpMessageHandlerMock.SetFixtureMessage(HttpStatusCode.OK, "account-meta");
306+
307+
// Act
308+
_ = await _subject.AccountMetaAsync(account);
309+
310+
// Assert
311+
_httpMessageHandlerMock.AssertRequestUri(HttpMethod.Get, $"/account-meta/{account}");
312+
}
313+
314+
[Test]
315+
[TestCase("qrBLomsmaSJ1ttBmS3WPmPpWLAUDKFwiF9Q")]
316+
public void GetAccountMetaAsync_WithInvalidAccount_ShouldThrowExceptionAsync(string account)
317+
{
318+
// Act
319+
var ex = Assert.ThrowsAsync<ArgumentException>(() => _subject.AccountMetaAsync(account));
320+
321+
// Assert
322+
Assert.IsNotNull(ex);
323+
Assert.That(ex!.Message, Is.EqualTo("Value should be a valid account address (Parameter 'account')"));
324+
}
325+
286326
[Test]
287327
[TestCase(null, 50, 5)]
288328
[TestCase("", 100, 0)]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"account": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
3+
"kycApproved": true,
4+
"xummPro": true,
5+
"avatar": "https://xumm.app/avatar/rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ.png",
6+
"xummProfile": {
7+
"accountAlias": "XRPL Labs - Wietse Wind",
8+
"ownerAlias": "Wietse Wind"
9+
},
10+
"thirdPartyProfiles": [
11+
{
12+
"accountAlias": "Wietse Wind",
13+
"source": "xumm.app"
14+
},
15+
{
16+
"accountAlias": "wietse.com",
17+
"source": "xrpl"
18+
}
19+
],
20+
"globalid": {
21+
"linked": "2021-06-29T10:22:25.123Z",
22+
"profileUrl": "https://global.id/wietse"
23+
}
24+
}

src/XUMM.NET.SDK.Tests/Fixtures/MiscFixtures.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Text.Json;
34
using XUMM.NET.SDK.Models.Misc;
45

@@ -186,4 +187,35 @@ internal static class MiscFixtures
186187
}
187188
}
188189
};
190+
191+
internal static XummAccountMetaResponse XummAccountMeta => new()
192+
{
193+
Account = "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
194+
KycApproved = true,
195+
XummPro = true,
196+
Avatar = "https://xumm.app/avatar/rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ.png",
197+
XummProfile = new()
198+
{
199+
AccountAlias = "XRPL Labs - Wietse Wind",
200+
OwnerAlias = "Wietse Wind"
201+
},
202+
ThirdPartyProfiles = new()
203+
{
204+
new XummThirdPartyProfile()
205+
{
206+
AccountAlias="Wietse Wind",
207+
Source= "xumm.app"
208+
},
209+
new XummThirdPartyProfile()
210+
{
211+
AccountAlias= "wietse.com",
212+
Source= "xrpl"
213+
}
214+
},
215+
GlobaliD = new()
216+
{
217+
Linked = new DateTime(2021, 06, 29, 10, 22, 25, 123, DateTimeKind.Utc),
218+
ProfileUrl = "https://global.id/wietse"
219+
}
220+
};
189221
}

src/XUMM.NET.SDK.Tests/XUMM.NET.SDK.Tests.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
<Nullable>enable</Nullable>
77
<IsPackable>false</IsPackable>
88
</PropertyGroup>
9-
9+
1010
<ItemGroup>
11+
<Content Include="Data\account-meta.json">
12+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
13+
</Content>
1114
<Content Include="Data\user-tokens.json">
1215
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1316
</Content>

src/XUMM.NET.SDK/Clients/Interfaces/IXummMiscClient.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface IXummMiscClient
1515
Task<XummCuratedAssets> GetCuratedAssetsAsync();
1616

1717
/// <summary>
18-
/// Fetch transaction & outcome live from XRP ledger full history nodes (through the XUMM platform) containing parsed
18+
/// Fetch transaction and outcome live from XRP ledger full history nodes (through the XUMM platform) containing parsed
1919
/// transaction outcome balance mutations
2020
/// </summary>
2121
/// <param name="txHash">The transaction hash (64 hexadecimal characters)</param>
@@ -45,6 +45,12 @@ public interface IXummMiscClient
4545
/// <param name="userTokens">List of User Token UUID's to check and return in the response (validity)</param>
4646
Task<XummUserTokens> VerifyUserTokensAsync(string[] userTokens);
4747

48+
/// <summary>
49+
/// Fetch the account meta for a XUMM user (based on a public XRPL account address, r...)
50+
/// </summary>
51+
/// <param name="account">Account address, eg. rBLomsmaSJ1ttBmS3WPmPpWLAUDKFwiF9Q</param>
52+
Task<XummAccountMetaResponse> AccountMetaAsync(string account);
53+
4854
/// <summary>
4955
/// Get an avatar (gravatar or personal avatar)
5056
/// </summary>

src/XUMM.NET.SDK/Clients/XummMiscClient.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ public async Task<XummUserTokens> VerifyUserTokensAsync(string[] userTokens)
108108
return await _httpClient.PostAsync<XummUserTokens>("user-tokens", request);
109109
}
110110

111+
/// <inheritdoc />
112+
public async Task<XummAccountMetaResponse> AccountMetaAsync(string account)
113+
{
114+
if (!account.IsAccountAddress())
115+
{
116+
throw new ArgumentException("Value should be a valid account address", nameof(account));
117+
}
118+
119+
return await _httpClient.GetAsync<XummAccountMetaResponse>($"account-meta/{account}");
120+
}
121+
111122
/// <inheritdoc />
112123
public string GetAvatarUrl(string account, int dimensions, int padding)
113124
{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Collections.Generic;
2+
using System.Text.Json.Serialization;
3+
4+
namespace XUMM.NET.SDK.Models.Misc
5+
{
6+
public class XummAccountMetaResponse
7+
{
8+
[JsonPropertyName("account")]
9+
public string Account { get; set; } = default!;
10+
11+
[JsonPropertyName("kycApproved")]
12+
public bool KycApproved { get; set; }
13+
14+
[JsonPropertyName("xummPro")]
15+
public bool XummPro { get; set; }
16+
17+
[JsonPropertyName("avatar")]
18+
public string Avatar { get; set; } = default!;
19+
20+
[JsonPropertyName("xummProfile")]
21+
public XummProfile XummProfile { get; set; } = default!;
22+
23+
[JsonPropertyName("thirdPartyProfiles")]
24+
public List<XummThirdPartyProfile> ThirdPartyProfiles { get; set; } = new List<XummThirdPartyProfile>();
25+
26+
[JsonPropertyName("globalid")]
27+
public XummGlobaliD GlobaliD { get; set; } = default!;
28+
}
29+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Text.Json.Serialization;
3+
4+
namespace XUMM.NET.SDK.Models.Misc
5+
{
6+
public class XummGlobaliD
7+
{
8+
[JsonPropertyName("linked")]
9+
public DateTime? Linked { get; set; }
10+
11+
[JsonPropertyName("profileUrl")]
12+
public string? ProfileUrl { get; set; }
13+
}
14+
}

0 commit comments

Comments
 (0)