Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
TokenDetailsViewModel.cs
1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
16using NeuroFeatures;
20using ShimSkiaSharp;
21using System.Collections.ObjectModel;
22using System.ComponentModel;
23using System.Globalization;
24using System.Text;
25using System.Web;
26using System.Xml;
27using Waher.Content;
31using Waher.Security;
32
34{
41 {
42 private readonly TokenDetailsNavigationArgs? navigationArguments = Args;
43 private readonly TokenDetailsPage page = Page;
44
46 public override async Task OnInitializeAsync()
47 {
48 await base.OnInitializeAsync();
49
50 if (this.navigationArguments is not null)
51 {
52 this.Created = this.navigationArguments.Token?.Created;
53 this.Updated = this.navigationArguments.Token?.Updated;
54 this.Expires = this.navigationArguments.Token?.Expires;
55 this.ArchiveRequired = this.navigationArguments.Token?.ArchiveRequired;
56 this.ArchiveOptional = this.navigationArguments.Token?.ArchiveOptional;
57 this.SignatureTimestamp = this.navigationArguments.Token?.SignatureTimestamp;
58 this.Signature = this.navigationArguments.Token?.Signature;
59 this.DefinitionSchemaDigest = this.navigationArguments.Token?.DefinitionSchemaDigest;
60 this.DefinitionSchemaHashFunction = this.navigationArguments.Token?.DefinitionSchemaHashFunction;
61 this.CreatorCanDestroy = this.navigationArguments.Token?.CreatorCanDestroy ?? false;
62 this.OwnerCanDestroyBatch = this.navigationArguments.Token?.OwnerCanDestroyBatch ?? false;
63 this.OwnerCanDestroyIndividual = this.navigationArguments.Token?.OwnerCanDestroyIndividual ?? false;
64 this.CertifierCanDestroy = this.navigationArguments.Token?.CertifierCanDestroy ?? false;
65 this.FriendlyName = this.navigationArguments.Token?.FriendlyName;
66 this.Category = this.navigationArguments.Token?.Category;
67 this.Description = this.navigationArguments.Token?.Description is null ? null : await this.navigationArguments.Token.Description.MarkdownToParsedXaml();
68 this.GlyphContentType = this.navigationArguments.Token?.GlyphContentType;
69 this.Ordinal = this.navigationArguments.Token?.Ordinal;
70 this.Value = this.navigationArguments.Token?.Value;
71 this.TokenIdMethod = this.navigationArguments.Token?.TokenIdMethod;
72 this.TokenId = this.navigationArguments.Token?.TokenId;
73 this.ShortTokenId = this.navigationArguments.Token?.ShortTokenId;
74 this.Visibility = this.navigationArguments.Token?.Visibility;
75 this.Creator = this.navigationArguments.Token?.Creator;
76 this.CreatorFriendlyName = await ContactInfo.GetFriendlyName(this.navigationArguments.Token?.Creator);
77 this.CreatorJid = this.navigationArguments.Token?.CreatorJid;
78 this.Owner = this.navigationArguments.Token?.Owner;
79 this.OwnerFriendlyName = await ContactInfo.GetFriendlyName(this.navigationArguments.Token?.Owner);
80 this.OwnerJid = this.navigationArguments.Token?.OwnerJid;
81 this.BatchSize = this.navigationArguments.Token?.BatchSize;
82 this.TrustProvider = this.navigationArguments.Token?.TrustProvider;
83 this.TrustProviderFriendlyName = await ContactInfo.GetFriendlyName(this.navigationArguments.Token?.TrustProvider);
84 this.TrustProviderJid = this.navigationArguments.Token?.TrustProviderJid;
85 this.Currency = this.navigationArguments.Token?.Currency;
86 this.Reference = this.navigationArguments.Token?.Reference;
87 this.Definition = this.navigationArguments.Token?.Definition;
88 this.DefinitionNamespace = this.navigationArguments.Token?.DefinitionNamespace;
89 this.CreationContract = this.navigationArguments.Token?.CreationContract;
90 this.OwnershipContract = this.navigationArguments.Token?.OwnershipContract;
91 this.GlyphImage = this.navigationArguments.Token?.GlyphImage;
92 this.HasGlyphImage = this.navigationArguments.Token?.HasGlyphImage ?? false;
93 this.GlyphWidth = this.navigationArguments.Token?.GlyphWidth;
94 this.GlyphHeight = this.navigationArguments.Token?.GlyphHeight;
95 this.TokenXml = this.navigationArguments.Token?.Token.ToXml();
96 this.IsMyToken = string.Equals(this.OwnerJid, ServiceRef.XmppService.BareJid, StringComparison.OrdinalIgnoreCase);
97 this.HasStateMachine = this.navigationArguments.Token?.HasStateMachine ?? false;
98 this.HasEmbeddedLayout = this.navigationArguments.Token?.HasEmbeddedLayout ?? false;
99
100 if (!string.IsNullOrEmpty(this.navigationArguments.Token?.Reference))
101 {
102 if (Uri.TryCreate(this.navigationArguments.Token?.Reference, UriKind.Absolute, out Uri? RefUri) &&
103 RefUri.Scheme.ToLower(CultureInfo.InvariantCulture) is string s &&
104 (s == "http" || s == "https"))
105 {
106 this.page.AddLink(this, ServiceRef.Localizer[nameof(AppResources.Reference)], s); // TODO: Replace with grouped collection, when this works in Maui.
107 }
108 }
109
110 if (this.navigationArguments.Token?.Tags is not null)
111 {
112 foreach (TokenTag Tag in this.navigationArguments.Token.Tags)
113 this.page.AddLink(this, Tag.Name, Tag.Value?.ToString() ?? string.Empty); // TODO: Replace with grouped collection, when this works in Maui.
114 }
115
116 if (this.TokenId is not null)
117 this.GenerateQrCode(Constants.UriSchemes.CreateTokenUri(this.TokenId));
118
119 await this.Populate(ServiceRef.Localizer[nameof(AppResources.Witness)], string.Empty, this.navigationArguments.Token?.Witness, null, this.Witnesses);
120 await this.Populate(ServiceRef.Localizer[nameof(AppResources.Certifier)], ServiceRef.Localizer[nameof(AppResources.CertifierJid)], this.navigationArguments.Token?.Certifier, this.navigationArguments.Token?.CertifierJids, this.Certifiers);
121 await this.Populate(ServiceRef.Localizer[nameof(AppResources.Valuator)], string.Empty, this.navigationArguments.Token?.Valuator, null, this.Valuators);
122 await this.Populate(ServiceRef.Localizer[nameof(AppResources.Assessor)], string.Empty, this.navigationArguments.Token?.Assessor, null, this.Assessors);
123
124 this.Tags.Clear();
125
126 if (this.navigationArguments.Token?.Tags is not null)
127 {
128 foreach (TokenTag Tag in this.navigationArguments.Token.Tags)
129 this.Tags.Add(Tag);
130 }
131
132 StringBuilder sb = new();
133 string Domain = this.TokenId?.After("@") ?? string.Empty;
134 Domain = Domain.After("."); // Remove last sub-domain, corresponding to the component hosting the token.
135
136 sb.Append("https://");
137 sb.Append(Domain);
138 sb.Append("/ValidationSchema.md?NS=");
139 sb.Append(HttpUtility.UrlEncode(this.DefinitionNamespace));
140 sb.Append("&H=");
141
142 if (this.DefinitionSchemaDigest is not null)
143 sb.Append(HttpUtility.UrlEncode(Convert.ToBase64String(this.DefinitionSchemaDigest)));
144
145 sb.Append("&Download=1");
146
147 this.DefinitionSchemaUrl = sb.ToString(); // TODO: The above assume contract hosted by the TAG Neuron. URL should be retrieved using API, or be standardized.
148 }
149 }
150
151 private async Task Populate(string LegalIdLabel, string JidLabel, string[]? LegalIds, string[]? Jids, ObservableCollection<PartItem> Parts)
152 {
153 int i, c = LegalIds?.Length ?? 0;
154 int d = Jids?.Length ?? 0;
155 string FriendlyName;
156 string Jid;
157
158 Parts.Clear();
159
160 for (i = 0; i < c; i++)
161 {
162 FriendlyName = await ContactInfo.GetFriendlyName(LegalIds![i]);
163 Jid = i < d ? (Jids![i] ?? string.Empty) : string.Empty;
164
165 Parts.Add(new PartItem(LegalIds[i], Jid, FriendlyName));
166
167 this.page.AddLegalId(this, LegalIdLabel, FriendlyName, LegalIds[i]); // TODO: Replace with grouped collection, when this works in Maui.
168
169 if (!string.IsNullOrEmpty(Jid))
170 this.page.AddJid(this, JidLabel, Jid, LegalIds[i], FriendlyName); // TODO: Replace with grouped collection, when this works in Maui.
171 }
172 }
173
177 [ObservableProperty]
178 private string? definitionSchemaUrl;
179
180 #region Properties
181
185 public ObservableCollection<PartItem> Certifiers { get; } = [];
186
190 public ObservableCollection<PartItem> Valuators { get; } = [];
191
195 public ObservableCollection<PartItem> Assessors { get; } = [];
196
200 public ObservableCollection<PartItem> Witnesses { get; } = [];
201
205 public ObservableCollection<TokenTag> Tags { get; } = [];
206
210 [ObservableProperty]
211 private DateTime? created;
212
216 [ObservableProperty]
217 private DateTime? updated;
218
222 [ObservableProperty]
223 private DateTime? expires;
224
228 [ObservableProperty]
229 private Duration? archiveRequired;
230
234 [ObservableProperty]
235 private Duration? archiveOptional;
236
240 [ObservableProperty]
241 private DateTime? signatureTimestamp;
242
246 [ObservableProperty]
247 private byte[]? signature;
248
252 [ObservableProperty]
253 private byte[]? definitionSchemaDigest;
254
258 [ObservableProperty]
259 private HashFunction? definitionSchemaHashFunction;
260
264 [ObservableProperty]
265 private bool creatorCanDestroy;
266
270 [ObservableProperty]
271 private bool ownerCanDestroyBatch;
272
276 [ObservableProperty]
277 private bool ownerCanDestroyIndividual;
278
282 [ObservableProperty]
283 private bool certifierCanDestroy;
284
288 [ObservableProperty]
289 private string? friendlyName;
290
294 [ObservableProperty]
295 private string? category;
296
300 [ObservableProperty]
301 private object? description;
302
306 [ObservableProperty]
307 private string? glyphContentType;
308
312 [ObservableProperty]
313 private int? ordinal;
314
318 [ObservableProperty]
319 private decimal? value;
320
324 [ObservableProperty]
325 private TokenIdMethod? tokenIdMethod;
326
330 [ObservableProperty]
331 private string? tokenId;
332
336 [ObservableProperty]
337 private string? shortTokenId;
338
340 protected override void OnPropertyChanged(PropertyChangedEventArgs e)
341 {
342 base.OnPropertyChanged(e);
343
344 switch (e.PropertyName)
345 {
346 case nameof(this.ShortTokenId):
347 this.HasShortTokenId = !string.IsNullOrEmpty(this.ShortTokenId);
348 break;
349 }
350 }
351
355 [ObservableProperty]
356 private bool hasShortTokenId;
357
361 [ObservableProperty]
362 private string? tokenXml;
363
367 [ObservableProperty]
368 private ContractVisibility? visibility;
369
373 [ObservableProperty]
374 private string? creator;
375
379 [ObservableProperty]
380 private string? creatorFriendlyName;
381
385 [ObservableProperty]
386 private string? creatorJid;
387
391 [ObservableProperty]
392 private string? owner;
393
397 [ObservableProperty]
398 private string? ownerFriendlyName;
399
403 [ObservableProperty]
404 private string? ownerJid;
405
409 [ObservableProperty]
410 private int? batchSize;
411
415 [ObservableProperty]
416 private string? trustProvider;
417
421 [ObservableProperty]
422 private string? trustProviderFriendlyName;
423
427 [ObservableProperty]
428 private string? trustProviderJid;
429
433 [ObservableProperty]
434 private string? currency;
435
439 [ObservableProperty]
440 private string? reference;
441
445 [ObservableProperty]
446 private string? definition;
447
451 [ObservableProperty]
452 private string? definitionNamespace;
453
457 [ObservableProperty]
458 private string? creationContract;
459
463 [ObservableProperty]
464 private string? ownershipContract;
465
469 [ObservableProperty]
470 private ImageSource? glyphImage;
471
475 [ObservableProperty]
476 private bool hasGlyphImage;
477
481 [ObservableProperty]
482 private int? glyphWidth;
483
487 [ObservableProperty]
488 private int? glyphHeight;
489
493 [ObservableProperty]
494 private bool isMyToken;
495
499 [ObservableProperty]
500 private bool hasStateMachine;
501
505 [ObservableProperty]
506 private bool hasEmbeddedLayout;
507
508
509 #endregion
510
511 #region Commands
512
516 [RelayCommand]
517 public static async Task CopyToClipboard(object Parameter)
518 {
519 try
520 {
521 string s = Parameter?.ToString() ?? string.Empty;
522 int i = s.IndexOf('@');
523
524 if (i > 0 && Guid.TryParse(s[..i], out _))
525 {
526 await Clipboard.SetTextAsync(Constants.UriSchemes.NeuroFeature + ":" + s);
529 }
530 else
531 {
532 await Clipboard.SetTextAsync(s);
535 }
536 }
537 catch (Exception ex)
538 {
539 ServiceRef.LogService.LogException(ex);
541 }
542 }
543
547 [RelayCommand]
548 private static async Task ViewId(object Parameter)
549 {
550 string? LegalId = Parameter?.ToString();
551 if (string.IsNullOrEmpty(LegalId))
552 return;
553
554 try
555 {
557 }
558 catch (Exception ex)
559 {
561 }
562 }
563
567 [RelayCommand]
568 private static async Task ViewContract(object Parameter)
569 {
570 string? ContractId = Parameter?.ToString();
571 if (string.IsNullOrEmpty(ContractId))
572 return;
573
574 try
575 {
576 await ServiceRef.ContractOrchestratorService.OpenContract(ContractId, ServiceRef.Localizer[nameof(AppResources.PurposeReviewToken)], null);
577 }
578 catch (Exception ex)
579 {
581 }
582 }
583
587 [RelayCommand]
588 private async Task OpenChat(object Parameter)
589 {
590 string? s = Parameter?.ToString();
591 if (string.IsNullOrEmpty(s))
592 return;
593
594 string? BareJid;
595 string? LegalId;
596 string? FriendlyName;
597
598 switch (s)
599 {
600 case "Owner":
601 BareJid = this.OwnerJid;
602 LegalId = this.Owner;
603 FriendlyName = this.OwnerFriendlyName;
604 break;
605
606 case "Creator":
607 BareJid = this.CreatorJid;
608 LegalId = this.Creator;
609 FriendlyName = this.CreatorFriendlyName;
610 break;
611
612 case "TrustProvider":
613 BareJid = this.TrustProviderJid;
614 LegalId = this.TrustProvider;
615 FriendlyName = this.TrustProviderFriendlyName;
616 break;
617
618 default:
619 string[] Parts = s.Split(" | ");
620 if (Parts.Length != 3)
621 return;
622
623 BareJid = Parts[0];
624 LegalId = Parts[1];
625 FriendlyName = Parts[2];
626 break;
627 }
628
629 try
630 {
631 ChatNavigationArgs Args = new(LegalId, BareJid, FriendlyName);
632 await ServiceRef.NavigationService.GoToAsync(nameof(ChatPage), Args, BackMethod.Inherited, BareJid);
633 }
634 catch (Exception ex)
635 {
637 }
638 }
639
643 [RelayCommand]
644 private static async Task OpenLink(object Parameter)
645 {
646 if (Parameter is not null)
647 await App.OpenUrlAsync(Parameter.ToString()!);
648 }
649
653 [RelayCommand]
654 private async Task ShowM2mInfo()
655 {
656 if (this.Definition is null)
657 return;
658
659 try
660 {
661 byte[] Bin = Encoding.UTF8.GetBytes(this.Definition);
662 HttpFileUploadEventArgs e = await ServiceRef.XmppService.RequestUploadSlotAsync(this.TokenId + ".xml", "text/xml; charset=utf-8", Bin.Length);
663
664 if (e.Ok)
665 {
666 await e.PUT(Bin, "text/xml", (int)Constants.Timeouts.UploadFile.TotalMilliseconds);
667 await App.OpenUrlAsync(e.GetUrl);
668 }
669 else
670 await ServiceRef.UiService.DisplayException(e.StanzaError ?? new Exception(e.ErrorText));
671 }
672 catch (Exception ex)
673 {
675 }
676 }
677
681 [RelayCommand]
682 private async Task SendToContact()
683 {
684 TaskCompletionSource<ContactInfoModel?> Selected = new();
685 ContactListNavigationArgs ContactListArgs = new(ServiceRef.Localizer[nameof(AppResources.SendInformationTo)], Selected)
686 {
687 CanScanQrCode = true,
688 };
689
690 await ServiceRef.NavigationService.GoToAsync(nameof(MyContactsPage), ContactListArgs, BackMethod.Pop);
691
692 ContactInfoModel? Contact = await Selected.Task;
693 if (Contact is null)
694 return;
695
696 StringBuilder Markdown = new();
697
698 Markdown.Append("```");
699 Markdown.AppendLine(Constants.UriSchemes.NeuroFeature);
700 Markdown.AppendLine(this.TokenXml);
701 Markdown.AppendLine("```");
702
703 await ChatViewModel.ExecuteSendMessage(string.Empty, Markdown.ToString(), Contact.BareJid);
704
705 if (Contact.Contact is not null)
706 {
707 await Task.Delay(100); // Otherwise, page doesn't show properly. (Underlying timing issue. TODO: Find better solution.)
708
709 ChatNavigationArgs ChatArgs = new(Contact.Contact);
710 await ServiceRef.NavigationService.GoToAsync(nameof(ChatPage), ChatArgs, BackMethod.Inherited, Contact.BareJid);
711 }
712 }
713
717 [RelayCommand]
718 private async Task Share()
719 {
720 try
721 {
722 if (this.QrCodeBin is null)
723 return;
724
725 string FileName = "Token.QR." + InternetContent.GetFileExtension(this.QrCodeContentType);
726
727 await this.OpenQrPopup(this.FriendlyName);
728
729 //ServiceRef.PlatformSpecific.ShareImage(this.QrCodeBin, this.FriendlyName ?? string.Empty,
730 // ServiceRef.Localizer[nameof(AppResources.Share)], FileName);
731 }
732 catch (Exception ex)
733 {
734 ServiceRef.LogService.LogException(ex);
736 }
737 }
738
742 [RelayCommand]
743 private async Task PublishMarketplace()
744 {
745 try
746 {
747 CreationAttributesEventArgs e = await ServiceRef.XmppService.GetNeuroFeatureCreationAttributes();
749 Template.Visibility = ContractVisibility.Public;
750 NewContractNavigationArgs NewContractArgs = new(Template, true,
751 new Dictionary<CaseInsensitiveString, object>()
752 {
753 { "TokenID", this.TokenId ?? string.Empty },
754 { "Category", this.Category ?? string.Empty },
755 { "FriendlyName", this.FriendlyName ?? string.Empty },
756 { "CommissionPercent", e.Commission },
757 { "Currency", e.Currency }
758 });
759
760 Template.Parts =
761 [
762 new()
763 {
764 Role = "Seller",
765 LegalId = ServiceRef.TagProfile.LegalIdentity?.Id
766 },
767 new()
768 {
769 Role = "Auctioneer",
770 LegalId = e.TrustProviderId
771 }
772 ];
773
774 NewContractArgs.SuppressProposal(e.TrustProviderId);
775
776 await ServiceRef.NavigationService.GoToAsync(nameof(NewContractPage), NewContractArgs, BackMethod.CurrentPage);
777 }
778 catch (Exception ex)
779 {
781 }
782 }
783
787 [RelayCommand]
788 private async Task OfferToSell()
789 {
790 try
791 {
792 Dictionary<CaseInsensitiveString, object> Parameters = [];
793 string? TrustProviderId = null;
795 Template.Visibility = ContractVisibility.Public;
796
798 {
799 CreationAttributesEventArgs e = await ServiceRef.XmppService.GetNeuroFeatureCreationAttributes();
800 XmlDocument Doc = new()
801 {
802 PreserveWhitespace = true
803 };
804 Doc.LoadXml(Template.ForMachines.OuterXml);
805
806 TrustProviderId = e.TrustProviderId;
807
808 XmlNamespaceManager NamespaceManager = new(Doc.NameTable);
809 NamespaceManager.AddNamespace("nft", NeuroFeaturesClient.NamespaceNeuroFeatures);
810
811 string? SellerRole = Doc.SelectSingleNode("/nft:Transfer/nft:Seller/nft:RoleReference/@role", NamespaceManager)?.Value;
812 string? TrustProviderRole = Doc.SelectSingleNode("/nft:Transfer/nft:TrustProvider/nft:RoleReference/@role", NamespaceManager)?.Value;
813 string? TokenIdParameter = Doc.SelectSingleNode("/nft:Transfer/nft:TokenID/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
814 string? CurrencyParameter = Doc.SelectSingleNode("/nft:Transfer/nft:Currency/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
815 string? CommissionParameter = Doc.SelectSingleNode("/nft:Transfer/nft:CommissionPercent/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
816 string? OwnershipContractParameter = Doc.SelectSingleNode("/nft:Transfer/nft:OwnershipContract/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
817
818 if (Template.Parts is null)
819 {
820 List<Part> Parts = [];
821
822 if (!string.IsNullOrEmpty(SellerRole))
823 {
824 Parts.Add(new Part()
825 {
826 LegalId = ServiceRef.TagProfile.LegalIdentity?.Id,
827 Role = SellerRole
828 });
829 }
830
831 if (!string.IsNullOrEmpty(TrustProviderRole))
832 {
833 Parts.Add(new Part()
834 {
835 LegalId = e.TrustProviderId,
836 Role = TrustProviderRole
837 });
838 }
839
840 Template.Parts = [.. Parts];
841 Template.PartsMode = ContractParts.ExplicitlyDefined;
842 }
843 else
844 {
845 foreach (Part Part in Template.Parts)
846 {
847 if (Part.Role == SellerRole)
848 Part.LegalId = ServiceRef.TagProfile.LegalIdentity?.Id;
849 else if (Part.Role == TrustProviderRole)
850 Part.LegalId = e.TrustProviderId;
851 }
852 }
853
854 if (!string.IsNullOrEmpty(TokenIdParameter))
855 Parameters[TokenIdParameter] = this.TokenId ?? string.Empty;
856
857 if (!string.IsNullOrEmpty(CurrencyParameter))
858 Parameters[CurrencyParameter] = e.Currency;
859
860 if (!string.IsNullOrEmpty(CommissionParameter))
861 Parameters[CommissionParameter] = e.Commission;
862
863 if (!string.IsNullOrEmpty(OwnershipContractParameter))
864 Parameters[OwnershipContractParameter] = this.OwnershipContract ?? string.Empty;
865 }
866
867 NewContractNavigationArgs NewContractArgs = new(Template, true, Parameters);
868
869 if (!string.IsNullOrEmpty(TrustProviderId))
870 NewContractArgs.SuppressProposal(TrustProviderId);
871
872 await ServiceRef.NavigationService.GoToAsync(nameof(NewContractPage), NewContractArgs, BackMethod.CurrentPage);
873 }
874 catch (Exception ex)
875 {
877 }
878 }
879
883 [RelayCommand]
884 private async Task OfferToBuy()
885 {
886 try
887 {
888 Dictionary<CaseInsensitiveString, object> Parameters = [];
889 string? TrustProviderId = null;
891 Template.Visibility = ContractVisibility.Public;
892
894 {
895 CreationAttributesEventArgs e = await ServiceRef.XmppService.GetNeuroFeatureCreationAttributes();
896 XmlDocument Doc = new()
897 {
898 PreserveWhitespace = true
899 };
900 Doc.LoadXml(Template.ForMachines.OuterXml);
901
902 TrustProviderId = e.TrustProviderId;
903
904 XmlNamespaceManager NamespaceManager = new(Doc.NameTable);
905 NamespaceManager.AddNamespace("nft", NeuroFeaturesClient.NamespaceNeuroFeatures);
906
907 string? BuyerRole = Doc.SelectSingleNode("/nft:Transfer/nft:Buyer/nft:RoleReference/@role", NamespaceManager)?.Value;
908 string? SellerRole = Doc.SelectSingleNode("/nft:Transfer/nft:Seller/nft:RoleReference/@role", NamespaceManager)?.Value;
909 string? TrustProviderRole = Doc.SelectSingleNode("/nft:Transfer/nft:TrustProvider/nft:RoleReference/@role", NamespaceManager)?.Value;
910 string? TokenIdParameter = Doc.SelectSingleNode("/nft:Transfer/nft:TokenID/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
911 string? CurrencyParameter = Doc.SelectSingleNode("/nft:Transfer/nft:Currency/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
912 string? CommissionParameter = Doc.SelectSingleNode("/nft:Transfer/nft:CommissionPercent/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
913 string? OwnershipContractParameter = Doc.SelectSingleNode("/nft:Transfer/nft:OwnershipContract/nft:ParameterReference/@parameter", NamespaceManager)?.Value;
914
915 if (Template.Parts is null)
916 {
917 List<Part> Parts = [];
918
919 if (!string.IsNullOrEmpty(BuyerRole))
920 {
921 Parts.Add(new Part()
922 {
923 LegalId = ServiceRef.TagProfile.LegalIdentity?.Id,
924 Role = BuyerRole
925 });
926 }
927
928 if (!string.IsNullOrEmpty(SellerRole))
929 {
930 Parts.Add(new Part()
931 {
932 LegalId = this.Owner,
933 Role = SellerRole
934 });
935 }
936
937 if (!string.IsNullOrEmpty(TrustProviderRole))
938 {
939 Parts.Add(new Part()
940 {
941 LegalId = e.TrustProviderId,
942 Role = TrustProviderRole
943 });
944 }
945
946 Template.Parts = [.. Parts];
947 Template.PartsMode = ContractParts.ExplicitlyDefined;
948 }
949 else
950 {
951 foreach (Part Part in Template.Parts)
952 {
953 if (Part.Role == BuyerRole)
954 Part.LegalId = ServiceRef.TagProfile.LegalIdentity?.Id;
955 else if (Part.Role == SellerRole)
956 Part.LegalId = this.Owner;
957 else if (Part.Role == TrustProviderRole)
958 Part.LegalId = e.TrustProviderId;
959 }
960 }
961
962 if (!string.IsNullOrEmpty(TokenIdParameter))
963 Parameters[TokenIdParameter] = this.TokenId ?? string.Empty;
964
965 if (!string.IsNullOrEmpty(CurrencyParameter))
966 Parameters[CurrencyParameter] = e.Currency;
967
968 if (!string.IsNullOrEmpty(CommissionParameter))
969 Parameters[CommissionParameter] = e.Commission;
970
971 if (!string.IsNullOrEmpty(OwnershipContractParameter))
972 Parameters[OwnershipContractParameter] = this.OwnershipContract ?? string.Empty;
973 }
974
975 NewContractNavigationArgs NewContractArgs = new(Template, true, Parameters);
976
977 if (!string.IsNullOrEmpty(TrustProviderId))
978 NewContractArgs.SuppressProposal(TrustProviderId);
979
980 await ServiceRef.NavigationService.GoToAsync(nameof(NewContractPage), NewContractArgs, BackMethod.CurrentPage);
981 }
982 catch (Exception ex)
983 {
985 }
986 }
987
991 [RelayCommand]
992 private async Task ViewEvents()
993 {
994 if (this.TokenId is null)
995 return;
996
997 try
998 {
999 TokenEvent[] Events = this.TokenId is null ? [] : await ServiceRef.XmppService.GetNeuroFeatureEvents(this.TokenId);
1000 TokenEventsNavigationArgs Args = new(this.TokenId!, Events);
1001
1003 }
1004 catch (Exception ex)
1005 {
1007 }
1008 }
1009
1010 [RelayCommand]
1011 private async Task PresentEmbeddedLayout()
1012 {
1013 if (this.TokenId is null)
1014 return;
1015
1016 EmbeddedLayoutNavigationArgs Args = new(this.navigationArguments.Token);
1017
1019 }
1020
1024 [RelayCommand]
1025 private async Task PresentReport()
1026 {
1027 if (this.TokenId is null)
1028 return;
1029
1030 await this.ShowReport(new TokenPresentReport(this.TokenId));
1031 }
1032
1036 [RelayCommand]
1037 private async Task HistoryReport()
1038 {
1039 if (this.TokenId is null)
1040 return;
1041
1042 await this.ShowReport(new TokenHistoryReport(this.TokenId));
1043 }
1044
1048 [RelayCommand]
1049 private async Task StatesReport()
1050 {
1051 if (this.TokenId is null)
1052 return;
1053
1054 await this.ShowReport(new TokenStateDiagramReport(this.TokenId));
1055 }
1056
1060 [RelayCommand]
1061 private async Task ProfilingReport()
1062 {
1063 if (this.TokenId is null)
1064 return;
1065
1066 await this.ShowReport(new TokenProfilingReport(this.TokenId));
1067 }
1068
1072 [RelayCommand]
1073 private async Task VariablesReport()
1074 {
1075 if (this.TokenId is null)
1076 return;
1077
1078 try
1079 {
1080 CurrentStateEventArgs e = await ServiceRef.XmppService.GetNeuroFeatureCurrentState(this.TokenId);
1081 if (e.Ok)
1082 {
1084
1086 }
1087 else
1089 }
1090 catch (Exception ex)
1091 {
1093 }
1094 }
1095
1096 private async Task ShowReport(TokenReport Report)
1097 {
1098 try
1099 {
1100 MachineReportNavigationArgs Args = new(Report);
1101
1103 }
1104 catch (Exception ex)
1105 {
1107 }
1108 }
1109
1110 #endregion
1111
1112 #region ILinkableView
1113
1117 public override Task<string> Title => Task.FromResult<string>(this.FriendlyName ?? string.Empty);
1118
1119 #endregion
1120
1121
1122 }
1123}
Represents an instance of the Neuro-Access app.
Definition: App.xaml.cs:125
const string TokenConsignmentTemplate
Contract template for consigning the token to an auctioneer with the purpose of selling it.
Definition: Constants.cs:987
const string TransferTokenTemplate
Contract template for transferring a token from a seller to a buyer
Definition: Constants.cs:982
static readonly TimeSpan UploadFile
Upload file timeout
Definition: Constants.cs:712
const string NeuroFeature
eDaler URI Scheme (edaler)
Definition: Constants.cs:178
static string CreateTokenUri(string id)
Generates a Neuro-Feature ID Uri form the specified id.
Definition: Constants.cs:262
A set of never changing property constants and helpful values.
Definition: Constants.cs:24
A strongly-typed resource class, for looking up localized strings, etc.
static string Assessor
Looks up a localized string similar to Assessor.
static string SendInformationTo
Looks up a localized string similar to Send Information To?.
static string Reference
Looks up a localized string similar to Reference.
static string Certifier
Looks up a localized string similar to Certifier.
static string IdCopiedSuccessfully
Looks up a localized string similar to A link to the ID was copied to the clipboard....
static string TagValueCopiedToClipboard
Looks up a localized string similar to Tag value copied to clipboard.
static string Valuator
Looks up a localized string similar to Valuator.
static string SuccessTitle
Looks up a localized string similar to Success.
static string PurposeReviewToken
Looks up a localized string similar to Reviewing token where you are part..
static string ErrorTitle
Looks up a localized string similar to An error has occurred.
static string Witness
Looks up a localized string similar to Witness.
static string CertifierJid
Looks up a localized string similar to Certifier Address.
Contains information about a contact.
Definition: ContactInfo.cs:22
static async Task< string > GetFriendlyName(CaseInsensitiveString RemoteId)
Gets the friendly name of a remote identity (Legal ID or Bare JID).
Definition: ContactInfo.cs:258
Base class that references services in the app.
Definition: ServiceRef.cs:43
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
static IUiService UiService
Service serializing and managing UI-related tasks.
Definition: ServiceRef.cs:130
static INavigationService NavigationService
The navigation service for navigating between pages.
Definition: ServiceRef.cs:178
static ITagProfile TagProfile
TAG Profile service.
Definition: ServiceRef.cs:202
static IContractOrchestratorService ContractOrchestratorService
Contract orchestrator service.
Definition: ServiceRef.cs:238
static IReportingStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:370
static IXmppService XmppService
The XMPP service for XMPP communication.
Definition: ServiceRef.cs:190
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.
Navigation arguments used when navigating to the embedded layout page.
Holds navigation parameters specific to a report from a state-machine.
A page that allows the user to view a state-machine report.
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.
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.
Event arguments for callback methods to token creation attributes queries.
string TrustProviderId
Legal ID used by the trust provider to sign contracts.
decimal Commission
Minimum commission (in %) expected by the trust provider, in order to sign contract.
Event arguments for current state callback methods.
string CurrentState
Current state of state-machine.
Variables Variables
Current state-machine variables.
Abstract base class for token events.
Definition: TokenEvent.cs:12
const string NamespaceNeuroFeatures
Namespace for Neuro-Features.
Abstract base class for token tag references.
Definition: TokenTag.cs:12
abstract object Value
Object value.
Definition: TokenTag.cs:37
CaseInsensitiveString Name
Tag Name
Definition: TokenTag.cs:32
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
Definition: Contract.cs:22
string ForMachinesLocalName
Local name used by the root node of the machine-readable contents of the contract (ForMachines).
Definition: Contract.cs:294
XmlElement ForMachines
Machine-readable contents of the contract.
Definition: Contract.cs:276
Part[] Parts
Defined parts for the smart contract.
Definition: Contract.cs:258
string ForMachinesNamespace
Namespace used by the root node of the machine-readable contents of the contract (ForMachines).
Definition: Contract.cs:289
Abstract base class for contractual parameters
Definition: Parameter.cs:17
Class defining a part in a contract
Definition: Part.cs:30
string Role
Role of the part in the contract
Definition: Part.cs:57
Class defining a role
Definition: Role.cs:7
bool Ok
If the response is an OK result response (true), or an error response (false).
XmppException StanzaError
Any stanza error returned.
Event arguments for HTTP File Upload callback methods.
Task PUT(byte[] Content, string ContentType, int Timeout)
Uploads file content to the server.
Task GoToAsync(string Route)
Navigates to the specified route and pushes the page onto the navigation stack.
Task DisplayException(Exception Exception, string? Title=null)
Displays an alert/message box to the user.
Task< bool > DisplayAlert(string Title, string Message, string? Accept=null, string? Cancel=null)
Displays an alert/message box to the user.
Definition: ImplTypes.g.cs:58
BackMethod
Navigation Back Method
Definition: BackMethod.cs:7
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.
Definition: PartItem.cs:9
TokenIdMethod
By which mechanism the Token ID was created
Definition: Token.cs:24
ContractParts
How the parts of the contract are defined.
Definition: Part.cs:9
ContractVisibility
Visibility types for contracts.
Definition: Enumerations.cs:56
HashFunction
Hash method enumeration.
Definition: Hashes.cs:26
Represents a duration value, as defined by the xsd:duration data type: http://www....
Definition: Duration.cs:14