1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
18using System.Collections.ObjectModel;
19using System.ComponentModel;
20using System.Globalization;
43 protected override async Task OnInitialize()
45 await base.OnInitialize();
47 if (this.navigationArguments is not
null)
49 this.Created = this.navigationArguments.Token?.Created;
50 this.Updated = this.navigationArguments.Token?.Updated;
51 this.Expires = this.navigationArguments.Token?.Expires;
52 this.ArchiveRequired = this.navigationArguments.Token?.ArchiveRequired;
53 this.ArchiveOptional = this.navigationArguments.Token?.ArchiveOptional;
54 this.SignatureTimestamp = this.navigationArguments.Token?.SignatureTimestamp;
55 this.Signature = this.navigationArguments.Token?.Signature;
56 this.DefinitionSchemaDigest = this.navigationArguments.Token?.DefinitionSchemaDigest;
57 this.DefinitionSchemaHashFunction = this.navigationArguments.Token?.DefinitionSchemaHashFunction;
58 this.CreatorCanDestroy = this.navigationArguments.Token?.CreatorCanDestroy ??
false;
59 this.OwnerCanDestroyBatch = this.navigationArguments.Token?.OwnerCanDestroyBatch ??
false;
60 this.OwnerCanDestroyIndividual = this.navigationArguments.Token?.OwnerCanDestroyIndividual ??
false;
61 this.CertifierCanDestroy = this.navigationArguments.Token?.CertifierCanDestroy ??
false;
62 this.FriendlyName = this.navigationArguments.Token?.FriendlyName;
63 this.Category = this.navigationArguments.Token?.Category;
64 this.Description = this.navigationArguments.Token?.Description is
null ? null : await this.navigationArguments.Token.Description.MarkdownToParsedXaml();
65 this.GlyphContentType = this.navigationArguments.Token?.GlyphContentType;
66 this.Ordinal = this.navigationArguments.Token?.Ordinal;
67 this.Value = this.navigationArguments.Token?.Value;
68 this.TokenIdMethod = this.navigationArguments.Token?.TokenIdMethod;
69 this.TokenId = this.navigationArguments.Token?.TokenId;
70 this.ShortTokenId = this.navigationArguments.Token?.ShortTokenId;
71 this.Visibility = this.navigationArguments.Token?.Visibility;
72 this.Creator = this.navigationArguments.Token?.Creator;
74 this.CreatorJid = this.navigationArguments.Token?.CreatorJid;
75 this.Owner = this.navigationArguments.Token?.Owner;
77 this.OwnerJid = this.navigationArguments.Token?.OwnerJid;
78 this.BatchSize = this.navigationArguments.Token?.BatchSize;
79 this.TrustProvider = this.navigationArguments.Token?.TrustProvider;
81 this.TrustProviderJid = this.navigationArguments.Token?.TrustProviderJid;
82 this.Currency = this.navigationArguments.Token?.Currency;
83 this.Reference = this.navigationArguments.Token?.Reference;
84 this.Definition = this.navigationArguments.Token?.Definition;
85 this.DefinitionNamespace = this.navigationArguments.Token?.DefinitionNamespace;
86 this.CreationContract = this.navigationArguments.Token?.CreationContract;
87 this.OwnershipContract = this.navigationArguments.Token?.OwnershipContract;
88 this.GlyphImage = this.navigationArguments.Token?.GlyphImage;
89 this.HasGlyphImage = this.navigationArguments.Token?.HasGlyphImage ??
false;
90 this.GlyphWidth = this.navigationArguments.Token?.GlyphWidth;
91 this.GlyphHeight = this.navigationArguments.Token?.GlyphHeight;
92 this.TokenXml = this.navigationArguments.Token?.Token.ToXml();
93 this.IsMyToken =
string.Equals(this.OwnerJid,
ServiceRef.
XmppService.BareJid, StringComparison.OrdinalIgnoreCase);
94 this.HasStateMachine = this.navigationArguments.Token?.HasStateMachine ??
false;
96 if (!
string.IsNullOrEmpty(this.navigationArguments.Token?.Reference))
98 if (Uri.TryCreate(
this.navigationArguments.Token?.Reference, UriKind.Absolute, out Uri? RefUri) &&
99 RefUri.Scheme.ToLower(CultureInfo.InvariantCulture) is
string s &&
100 (s ==
"http" || s ==
"https"))
106 if (this.navigationArguments.Token?.Tags is not
null)
108 foreach (
TokenTag Tag
in this.navigationArguments.Token.Tags)
109 this.page.AddLink(
this, Tag.
Name, Tag.
Value?.ToString() ??
string.Empty);
112 if (this.TokenId is not
null)
115 await this.Populate(
ServiceRef.
Localizer[nameof(AppResources.Witness)],
string.Empty,
this.navigationArguments.Token?.Witness,
null,
this.Witnesses);
116 await this.Populate(
ServiceRef.
Localizer[nameof(AppResources.Certifier)],
ServiceRef.
Localizer[nameof(AppResources.CertifierJid)],
this.navigationArguments.Token?.Certifier,
this.navigationArguments.Token?.CertifierJids,
this.Certifiers);
117 await this.Populate(
ServiceRef.
Localizer[nameof(AppResources.Valuator)],
string.Empty,
this.navigationArguments.Token?.Valuator,
null,
this.Valuators);
118 await this.Populate(
ServiceRef.
Localizer[nameof(AppResources.Assessor)],
string.Empty,
this.navigationArguments.Token?.Assessor,
null,
this.Assessors);
122 if (this.navigationArguments.Token?.Tags is not
null)
124 foreach (
TokenTag Tag
in this.navigationArguments.Token.Tags)
128 StringBuilder sb =
new();
129 string Domain = this.TokenId?.After(
"@") ??
string.Empty;
130 Domain = Domain.After(
".");
132 sb.Append(
"https://");
134 sb.Append(
"/ValidationSchema.md?NS=");
135 sb.Append(HttpUtility.UrlEncode(
this.DefinitionNamespace));
138 if (this.DefinitionSchemaDigest is not
null)
139 sb.Append(HttpUtility.UrlEncode(Convert.ToBase64String(
this.DefinitionSchemaDigest)));
141 sb.Append(
"&Download=1");
143 this.DefinitionSchemaUrl = sb.ToString();
147 private async Task Populate(
string LegalIdLabel,
string JidLabel,
string[]? LegalIds,
string[]? Jids, ObservableCollection<PartItem> Parts)
149 int i, c = LegalIds?.Length ?? 0;
150 int d = Jids?.Length ?? 0;
156 for (i = 0; i < c; i++)
159 Jid = i < d ? (Jids![i] ??
string.Empty) :
string.Empty;
161 Parts.Add(
new PartItem(LegalIds[i], Jid, FriendlyName));
163 this.page.AddLegalId(
this, LegalIdLabel, FriendlyName, LegalIds[i]);
165 if (!
string.IsNullOrEmpty(Jid))
166 this.page.AddJid(
this, JidLabel, Jid, LegalIds[i], FriendlyName);
174 private string? definitionSchemaUrl;
181 public ObservableCollection<PartItem> Certifiers {
get; } = [];
186 public ObservableCollection<PartItem> Valuators {
get; } = [];
191 public ObservableCollection<PartItem> Assessors {
get; } = [];
196 public ObservableCollection<PartItem> Witnesses {
get; } = [];
201 public ObservableCollection<TokenTag> Tags {
get; } = [];
207 private DateTime? created;
213 private DateTime? updated;
219 private DateTime? expires;
237 private DateTime? signatureTimestamp;
243 private byte[]? signature;
249 private byte[]? definitionSchemaDigest;
261 private bool creatorCanDestroy;
267 private bool ownerCanDestroyBatch;
273 private bool ownerCanDestroyIndividual;
279 private bool certifierCanDestroy;
285 private string? friendlyName;
291 private string? category;
297 private object? description;
303 private string? glyphContentType;
309 private int? ordinal;
315 private decimal? value;
327 private string? tokenId;
333 private string? shortTokenId;
336 protected override void OnPropertyChanged(PropertyChangedEventArgs e)
338 base.OnPropertyChanged(e);
340 switch (e.PropertyName)
342 case nameof(this.ShortTokenId):
343 this.HasShortTokenId = !
string.IsNullOrEmpty(this.ShortTokenId);
352 private bool hasShortTokenId;
358 private string? tokenXml;
370 private string? creator;
376 private string? creatorFriendlyName;
382 private string? creatorJid;
388 private string? owner;
394 private string? ownerFriendlyName;
400 private string? ownerJid;
406 private int? batchSize;
412 private string? trustProvider;
418 private string? trustProviderFriendlyName;
424 private string? trustProviderJid;
430 private string? currency;
436 private string? reference;
442 private string? definition;
448 private string? definitionNamespace;
454 private string? creationContract;
460 private string? ownershipContract;
466 private ImageSource? glyphImage;
472 private bool hasGlyphImage;
478 private int? glyphWidth;
484 private int? glyphHeight;
490 private bool isMyToken;
496 private bool hasStateMachine;
506 public static async Task CopyToClipboard(
object Parameter)
510 string s =
Parameter?.ToString() ??
string.Empty;
511 int i = s.IndexOf(
'@');
513 if (i > 0 && Guid.TryParse(s[..i], out _))
521 await Clipboard.SetTextAsync(s);
537 private static async Task ViewId(
object Parameter)
540 if (
string.IsNullOrEmpty(LegalId))
557 private static async Task ViewContract(
object Parameter)
559 string? ContractId =
Parameter?.ToString();
560 if (
string.IsNullOrEmpty(ContractId))
577 private async Task OpenChat(
object Parameter)
580 if (
string.IsNullOrEmpty(s))
585 string? FriendlyName;
590 BareJid = this.OwnerJid;
591 LegalId = this.Owner;
592 FriendlyName = this.OwnerFriendlyName;
596 BareJid = this.CreatorJid;
597 LegalId = this.Creator;
598 FriendlyName = this.CreatorFriendlyName;
601 case "TrustProvider":
602 BareJid = this.TrustProviderJid;
603 LegalId = this.TrustProvider;
604 FriendlyName = this.TrustProviderFriendlyName;
608 string[] Parts = s.Split(
" | ");
609 if (Parts.Length != 3)
614 FriendlyName = Parts[2];
633 private static async Task OpenLink(
object Parameter)
643 private async Task ShowM2mInfo()
645 if (this.Definition is
null)
650 byte[] Bin = Encoding.UTF8.GetBytes(this.Definition);
671 private async Task SendToContact()
673 TaskCompletionSource<ContactInfoModel?> Selected =
new();
676 CanScanQrCode =
true,
685 StringBuilder Markdown =
new();
687 Markdown.Append(
"```");
689 Markdown.AppendLine(this.TokenXml);
690 Markdown.AppendLine(
"```");
694 if (Contact.
Contact is not
null)
696 await Task.Delay(100);
707 private async Task Share()
711 if (this.QrCodeBin is
null)
716 ServiceRef.PlatformSpecific.ShareImage(this.QrCodeBin, this.FriendlyName ??
string.Empty,
730 private async Task PublishMarketplace()
737 NewContractNavigationArgs NewContractArgs =
new(Template,
true,
738 new Dictionary<CaseInsensitiveString, object>()
740 {
"TokenID", this.TokenId ?? string.Empty },
741 {
"Category", this.Category ?? string.Empty },
742 {
"FriendlyName", this.FriendlyName ?? string.Empty },
743 {
"CommissionPercent", e.Commission },
744 {
"Currency", e.Currency }
757 LegalId = e.TrustProviderId
761 NewContractArgs.SuppressProposal(e.TrustProviderId);
775 private async Task OfferToSell()
779 Dictionary<CaseInsensitiveString, object> Parameters = [];
780 string? TrustProviderId =
null;
787 XmlDocument Doc =
new()
789 PreserveWhitespace =
true
793 TrustProviderId = e.TrustProviderId;
795 XmlNamespaceManager NamespaceManager =
new(Doc.NameTable);
798 string? SellerRole = Doc.SelectSingleNode(
"/nft:Transfer/nft:Seller/nft:RoleReference/@role", NamespaceManager)?.Value;
799 string? TrustProviderRole = Doc.SelectSingleNode(
"/nft:Transfer/nft:TrustProvider/nft:RoleReference/@role", NamespaceManager)?.Value;
800 string? TokenIdParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:TokenID/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
801 string? CurrencyParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:Currency/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
802 string? CommissionParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:CommissionPercent/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
803 string? OwnershipContractParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:OwnershipContract/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
805 if (Template.
Parts is
null)
807 List<Part> Parts = [];
809 if (!
string.IsNullOrEmpty(SellerRole))
818 if (!
string.IsNullOrEmpty(TrustProviderRole))
822 LegalId = e.TrustProviderId,
823 Role = TrustProviderRole
827 Template.Parts = [.. Parts];
836 else if (
Part.
Role == TrustProviderRole)
837 Part.LegalId = e.TrustProviderId;
841 if (!
string.IsNullOrEmpty(TokenIdParameter))
842 Parameters[TokenIdParameter] = this.TokenId ??
string.Empty;
844 if (!
string.IsNullOrEmpty(CurrencyParameter))
845 Parameters[CurrencyParameter] = e.Currency;
847 if (!
string.IsNullOrEmpty(CommissionParameter))
848 Parameters[CommissionParameter] = e.Commission;
850 if (!
string.IsNullOrEmpty(OwnershipContractParameter))
851 Parameters[OwnershipContractParameter] = this.OwnershipContract ??
string.Empty;
854 NewContractNavigationArgs NewContractArgs =
new(Template,
true, Parameters);
856 if (!
string.IsNullOrEmpty(TrustProviderId))
857 NewContractArgs.SuppressProposal(TrustProviderId);
871 private async Task OfferToBuy()
875 Dictionary<CaseInsensitiveString, object> Parameters = [];
876 string? TrustProviderId =
null;
883 XmlDocument Doc =
new()
885 PreserveWhitespace =
true
889 TrustProviderId = e.TrustProviderId;
891 XmlNamespaceManager NamespaceManager =
new(Doc.NameTable);
894 string? BuyerRole = Doc.SelectSingleNode(
"/nft:Transfer/nft:Buyer/nft:RoleReference/@role", NamespaceManager)?.Value;
895 string? SellerRole = Doc.SelectSingleNode(
"/nft:Transfer/nft:Seller/nft:RoleReference/@role", NamespaceManager)?.Value;
896 string? TrustProviderRole = Doc.SelectSingleNode(
"/nft:Transfer/nft:TrustProvider/nft:RoleReference/@role", NamespaceManager)?.Value;
897 string? TokenIdParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:TokenID/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
898 string? CurrencyParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:Currency/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
899 string? CommissionParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:CommissionPercent/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
900 string? OwnershipContractParameter = Doc.SelectSingleNode(
"/nft:Transfer/nft:OwnershipContract/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
902 if (Template.
Parts is
null)
904 List<Part> Parts = [];
906 if (!
string.IsNullOrEmpty(BuyerRole))
915 if (!
string.IsNullOrEmpty(SellerRole))
919 LegalId = this.Owner,
924 if (!
string.IsNullOrEmpty(TrustProviderRole))
928 LegalId = e.TrustProviderId,
929 Role = TrustProviderRole
933 Template.Parts = [.. Parts];
943 Part.LegalId = this.Owner;
944 else if (
Part.
Role == TrustProviderRole)
945 Part.LegalId = e.TrustProviderId;
949 if (!
string.IsNullOrEmpty(TokenIdParameter))
950 Parameters[TokenIdParameter] = this.TokenId ??
string.Empty;
952 if (!
string.IsNullOrEmpty(CurrencyParameter))
953 Parameters[CurrencyParameter] = e.Currency;
955 if (!
string.IsNullOrEmpty(CommissionParameter))
956 Parameters[CommissionParameter] = e.Commission;
958 if (!
string.IsNullOrEmpty(OwnershipContractParameter))
959 Parameters[OwnershipContractParameter] = this.OwnershipContract ??
string.Empty;
962 NewContractNavigationArgs NewContractArgs =
new(Template,
true, Parameters);
964 if (!
string.IsNullOrEmpty(TrustProviderId))
965 NewContractArgs.SuppressProposal(TrustProviderId);
979 private async Task ViewEvents()
981 if (this.TokenId is
null)
1001 private async Task PresentReport()
1003 if (this.TokenId is
null)
1013 private async Task HistoryReport()
1015 if (this.TokenId is
null)
1025 private async Task StatesReport()
1027 if (this.TokenId is
null)
1037 private async Task ProfilingReport()
1039 if (this.TokenId is
null)
1049 private async Task VariablesReport()
1051 if (this.TokenId is
null)
1066 catch (Exception ex)
1080 catch (Exception ex)
1088 #region ILinkableView
1093 public override Task<string> Title => Task.FromResult<
string>(this.FriendlyName ??
string.Empty);
The Application class, representing an instance of the Neuro-Access app.
static Task< bool > OpenUrlAsync(string Url)
Opens an URL in the application.
const string TokenConsignmentTemplate
Contract template for consigning the token to an auctioneer with the purpose of selling it.
const string TransferTokenTemplate
Contract template for transferring a token from a seller to a buyer
static readonly TimeSpan UploadFile
Upload file timeout
const string NeuroFeature
eDaler URI Scheme (edaler)
static string CreateTokenUri(string id)
Generates a Neuro-Feature ID Uri form the specified id.
A set of never changing property constants and helpful values.
Base class that references services in the app.
static ILogService LogService
Log service.
static IUiService UiService
Service serializing and managing UI-related tasks.
static ITagProfile TagProfile
TAG Profile service.
static IStringLocalizer Localizer
Localization service
static IContractOrchestratorService ContractOrchestratorService
Contract orchestrator service.
static IXmppService XmppService
The XMPP service for XMPP communication.
Holds navigation parameters specific to views displaying a list of contacts.
A page that displays a list of the current user's contacts.
The view model to bind to when displaying the list of contacts.
Contact Information model, including related notification information.
ContactInfo? Contact
Contact Information object in database.
CaseInsensitiveString? BareJid
Bare JID of contact.
Holds navigation parameters specific to views displaying a list of contacts.
A page that displays a list of the current user's contacts.
A page that allows the user to create a new contract.
A view model that holds the XMPP state.
Holds navigation parameters specific to a report from a state-machine.
A page that allows the user to view a state-machine report.
Abstract base class for token reports.
Holds navigation parameters specific to the current state of a state-machine.
A page that allows the user to view information about the current state of a state-machine.
Holds navigation parameters specific to a token.
A page that allows the user to view information about a token.
Holds navigation parameters containing the events of a token.
A page that allows the user to view information about a token.
Abstract base class for token events.
const string NamespaceNeuroFeatures
Namespace for Neuro-Features.
Static class managing encoding and decoding of internet content.
static string GetFileExtension(string ContentType)
Gets the file extension of an item, given its content type. It uses the TryGetFileExtension to see if...
Contains the definition of a contract
string ForMachinesLocalName
Local name used by the root node of the machine-readable contents of the contract (ForMachines).
XmlElement ForMachines
Machine-readable contents of the contract.
Part[] Parts
Defined parts for the smart contract.
string ForMachinesNamespace
Namespace used by the root node of the machine-readable contents of the contract (ForMachines).
Abstract base class for contractual parameters
Class defining a part in a contract
string Role
Role of the part in the contract
bool Ok
If the response is an OK result response (true), or an error response (false).
XmppException StanzaError
Any stanza error returned.
string ErrorText
Any error specific text.
Event arguments for HTTP File Upload callback methods.
async Task PUT(byte[] Content, string ContentType, int Timeout)
Uploads file content to the server.
Task DisplayException(Exception Exception, string? Title=null)
Displays an alert/message box to the user.
Task GoToAsync(string Route, BackMethod BackMethod=BackMethod.Inherited, string? UniqueId=null)
Navigates the AppShell to the specified route, with page arguments to match.
Task< bool > DisplayAlert(string Title, string Message, string? Accept=null, string? Cancel=null)
Displays an alert/message box to the user.
BackMethod
Navigation Back Method
class TokenPresentReport(string TokenId)
Represent a report of the present state of a token and the underlying state-machine.
class TokenStateDiagramReport(string TokenId)
Represent a state diagram of a token and the underlying state-machine.
class TokenHistoryReport(string TokenId)
Represent a report of the historical states of a token and the underlying state-machine.
class TokenProfilingReport(string TokenId)
Represent a profiling report of a token and the underlying state-machine.
partial class TokenDetailsViewModel(TokenDetailsPage Page, TokenDetailsNavigationArgs? Args)
The view model to bind to for when displaying the contents of a token.
class PartItem(string LegalId, string Jid, string FriendlyName)
Represents a part related to a token.
TokenIdMethod
By which mechanism the Token ID was created
ContractParts
How the parts of the contract are defined.
ContractVisibility
Visibility types for contracts.
HashFunction
Hash method enumeration.
Represents a duration value, as defined by the xsd:duration data type: http://www....