3using System.Collections.Generic;
6using System.Text.RegularExpressions;
7using System.Threading.Tasks;
54 #region Smart Contract interface
68 internal static async Task ContractSigned(
Contract Contract,
bool ContractIsLocked,
69 Dictionary<CaseInsensitiveString, Parameter> TransientParameters,
75 if ((TransientParameters?.Count ?? 0) > 0)
77 await RejectContract(
Contract, ContractIsLocked,
78 "Transient parameters not permitted for transparency reasons.",
83 switch (
Contract.ForMachinesLocalName)
86 if (!OnlyMissingTrustProvider(
Contract, out
string TrustProviderRole, out XmlDocument ForMachines))
89 await CreateTokens(ForMachines.DocumentElement,
Contract, ContractIsLocked, TrustProviderRole, Legal,
EDaler);
93 if (!OnlyMissingTrustProvider(
Contract, out TrustProviderRole, out ForMachines))
96 await DestroyTokens(ForMachines.DocumentElement,
Contract, ContractIsLocked, TrustProviderRole, Legal,
EDaler);
100 if (!OnlyMissingTrustProvider(
Contract, out TrustProviderRole, out ForMachines))
103 await TransferTokens(ForMachines.DocumentElement,
Contract, ContractIsLocked, TrustProviderRole, Legal,
EDaler);
107 await RejectContract(
Contract, ContractIsLocked,
"Rejected Neuro-Feature contract: Unrecognized element: " +
Contract.ForMachinesLocalName,
true, Legal,
EDaler);
114 return RejectContract(
Contract, ContractIsLocked, Reason, FailContract, Legal,
EDaler,
string.Empty);
117 internal static async Task RejectContract(
Contract Contract,
bool ContractIsLocked,
string Reason,
bool FailContract,
126 if (ContractIsLocked)
137 await Legal.SendContractUpdatedEvent(
Contract,
false);
145 Dictionary<CaseInsensitiveString, bool> SendTo =
new Dictionary<CaseInsensitiveString, bool>();
152 await
EDaler.Server.SendMessage(
"chat",
string.Empty,
EDaler.MainDomain.Address, Jid,
"en",
153 "<body>" +
XML.
Encode(Reason) +
"</body>");
157 private static bool OnlyMissingTrustProvider(
Contract Contract, out
string TrustProviderRole, out XmlDocument ForMachines)
159 TrustProviderRole =
null;
165 if ((
Contract.Roles?.Length ?? 0) < 2)
168 string CreatorRole =
null;
169 string OwnerRole =
null;
172 ForMachines =
new XmlDocument()
174 PreserveWhitespace =
true
176 ForMachines.LoadXml(
Contract.ForMachines);
178 foreach (XmlElement E
in ForMachines.DocumentElement.ChildNodes)
180 if (E.NamespaceURI !=
Contract.ForMachinesNamespace)
185 case "TrustProvider":
201 if (
string.IsNullOrEmpty(TrustProviderRole) || !
string.IsNullOrEmpty(TrustProviderLegalId))
204 if (
string.IsNullOrEmpty(OwnerRole))
205 OwnerRole = CreatorRole;
207 Dictionary<string, SignatureStat> Signatures =
new Dictionary<string, SignatureStat>();
227 Signatures[
Role.
Name] =
new SignatureStat()
241 if (Signatures.TryGetValue(
Signature.Role, out SignatureStat Stat))
247 foreach (SignatureStat Stat
in Signatures.Values)
249 if (Stat.Count < Stat.Min || Stat.Count > Stat.Max)
268 private class SignatureStat
275 private class TokenIDReference
281 public int ShortIdLength;
282 public string ShortIdAlphabet;
287 int ShortIdLength =
XML.
Attribute(Value,
"shortIdLength", 0);
288 string ShortIdAlphabet =
XML.
Attribute(Value,
"shortIdAlphabet",
"0123456789");
290 foreach (XmlNode N
in Value.ChildNodes)
292 if (!(N is XmlElement E))
298 return new TokenIDReference()
300 TokenId = Guid.NewGuid(),
302 ShortIdLength = ShortIdLength,
303 ShortIdAlphabet = ShortIdAlphabet
307 return new TokenIDReference()
309 TokenId = Guid.Empty,
311 ShortIdLength = ShortIdLength,
312 ShortIdAlphabet = ShortIdAlphabet
318 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid Token ID.",
true, Legal,
EDaler);
322 if (s != s.ToLower())
324 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Token IDs must be lower-case.",
true, Legal,
EDaler);
328 if (!Guid.TryParse(s, out Guid TokenGuid))
330 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Token IDs must be GUIDs.",
true, Legal,
EDaler);
334 return new TokenIDReference()
338 ShortIdLength = ShortIdLength,
339 ShortIdAlphabet = ShortIdAlphabet
344 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Undefined Token ID.",
true, Legal,
EDaler);
353 if (tokenCache.TryGetValue(TokenId, out
Token Result))
370 StringBuilder Xml =
new StringBuilder();
372 Xml.Append(
"<token id='");
374 Xml.Append(
"' xmlns='");
384 if (!(Result is
null))
385 tokenCache[TokenId] = Result;
390 internal static async Task<(int, int, int)> DeleteExpiredTokens()
420 return (NrTokens, NrEvents, NrTags);
425 #region Create Contract
430 private enum CommissionPaidBy
443 private static async Task<bool> CreateTokens(XmlElement Create,
Contract Contract,
bool ContractIsLocked,
string TrustProviderRole,
LegalComponent Legal,
446 Dictionary<Guid, TokenIDReference> ProposedTokenIDs =
new Dictionary<Guid, TokenIDReference>();
447 List<TokenIDReference> AllTokenIDs =
new List<TokenIDReference>();
448 SortedDictionary<CaseInsensitiveString, TokenTagReference> TagReferences =
null;
456 string Currency =
null;
457 string Reference =
null;
458 string FriendlyName =
null;
459 string Category =
null;
460 string Description =
null;
461 string GlyphContentType =
null;
463 XmlElement Definition =
null;
464 decimal? Value =
null;
465 decimal? CommissionPercent =
null;
466 CommissionPaidBy CommissionPaidBy = CommissionPaidBy.Owner;
467 int? GlyphWidth =
null;
468 int? GlyphHeight =
null;
469 DateTime Expires = DateTime.MaxValue;
470 bool CreatorCanDestroy =
false;
471 bool OwnerCanDestroyBatch =
false;
472 bool OwnerCanDestroyIndividual =
false;
473 bool CertifierCanDestroy =
false;
475 foreach (XmlElement E
in Create.ChildNodes)
477 if (E.NamespaceURI ==
Contract.ForMachinesNamespace)
482 TokenIDReference TokenRef = await GetTokenId(E,
Contract, ContractIsLocked, Legal,
EDaler);
483 if (TokenRef is
null)
486 AllTokenIDs.Add(TokenRef);
490 if (ProposedTokenIDs.ContainsKey(TokenRef.TokenId))
492 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Duplicate Token IDs used.",
true, Legal,
EDaler);
496 ProposedTokenIDs[TokenRef.TokenId] = TokenRef;
524 case "TrustProvider":
531 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid value.",
true, Legal,
EDaler);
541 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid currency.",
true, Legal,
EDaler);
548 case "CommissionPercent":
551 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid commission (%).",
true, Legal,
EDaler);
555 CommissionPercent = d2;
558 case "CommissionPaidBy":
559 if (!Enum.TryParse(E.InnerText, out CommissionPaidBy CommissionPaidBy2))
561 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid commission payer.",
true, Legal,
EDaler);
565 CommissionPaidBy = CommissionPaidBy2;
569 if (!(await
PaiwiseProcessor.GetParameterValue(E,
Contract) is DateTime TP) || (Expires = TP.ToUniversalTime()).Date <= DateTime.UtcNow.Date)
571 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid expiry date.",
true, Legal,
EDaler);
576 case "CreatorCanDestroy":
579 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid CreatorCanDestroy property value.",
true, Legal,
EDaler);
583 CreatorCanDestroy = b;
586 case "OwnerCanDestroyBatch":
589 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid OwnerCanDestroyBatch property value.",
true, Legal,
EDaler);
593 OwnerCanDestroyBatch = b2;
596 case "OwnerCanDestroyIndividual":
599 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid OwnerCanDestroyIndividual property value.",
true, Legal,
EDaler);
603 OwnerCanDestroyIndividual = b4;
606 case "CertifierCanDestroy":
609 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid CertifierCanDestroy property value.",
true, Legal,
EDaler);
613 CertifierCanDestroy = b3;
619 if (Ref is
string s3)
625 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid reference.",
true, Legal,
EDaler);
631 foreach (XmlNode N
in E.ChildNodes)
633 if (N is XmlElement E2)
635 if (Definition is
null)
639 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Definition can only be one element.",
true, Legal,
EDaler);
647 if (TagReferences is
null)
648 TagReferences =
new SortedDictionary<CaseInsensitiveString, TokenTagReference>();
652 if (TagReferences.ContainsKey(TagName))
654 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Duplicated tag name.",
true, Legal,
EDaler);
660 if (TagValue is decimal d3)
662 else if (TagValue is
string s)
666 else if (TagValue is
bool b5)
668 else if (TagValue is DateTime TP2)
670 else if (TagValue is TimeSpan TS)
674 else if (TagValue is
byte[] Bin)
676 else if (TagValue is
null)
678 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Unable to evaluate tag " + TagName +
".",
true, Legal,
EDaler);
683 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Unrecognized value for tag " + TagName +
".",
true, Legal,
EDaler);
691 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid friendly name.",
true, Legal,
EDaler);
695 FriendlyName = Category = Description = s4;
701 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid category.",
true, Legal,
EDaler);
711 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid description.",
true, Legal,
EDaler);
722 if (!GlyphContentType.StartsWith(
"image/"))
724 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid glyph content type.",
true, Legal,
EDaler);
728 Glyph = Convert.FromBase64String(E.InnerText);
731 if (!(Decoded is SKImage Image))
733 if (Decoded is IDisposable Disposable)
734 Disposable.Dispose();
736 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Glyph not an image.",
true, Legal,
EDaler);
740 GlyphWidth = Image.Width;
741 GlyphHeight = Image.Height;
747 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid glyph.",
true, Legal,
EDaler);
755 if (AllTokenIDs.Count == 0)
757 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: No Token IDs.",
true, Legal,
EDaler);
761 if (Definition is
null)
763 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Definition missing.",
true, Legal,
EDaler);
769 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Definition schema not found.",
true, Legal,
EDaler);
773 if (
string.IsNullOrEmpty(CreatorId))
775 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Missing Creator ID.",
true, Legal,
EDaler);
779 if (!Value.HasValue || Value.Value <= 0)
781 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Value must be positive.",
true, Legal,
EDaler);
785 if (
string.IsNullOrEmpty(Currency) || Currency.Length != 3)
787 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid currency.",
true, Legal,
EDaler);
791 if (
string.IsNullOrEmpty(TrustProviderRole))
793 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Trust Provider role not defined.",
true, Legal,
EDaler);
797 if (!
string.IsNullOrEmpty(TrustProviderLegalId) &&
800 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Trust Provider ID does not represent the current server.",
true, Legal,
EDaler);
804 if (!CommissionPercent.HasValue)
806 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Commission missing.",
true, Legal,
EDaler);
812 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Commission too low.",
true, Legal,
EDaler);
816 if (Expires.Date <= DateTime.UtcNow.Date)
818 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Must expire on a future date, if to expire.",
true, Legal,
EDaler);
823 DateTime.UtcNow.Date +
Contract.Duration.Value < Expires.Date.AddDays(1))
825 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Duration must cover expiry date.",
true, Legal,
EDaler);
829 if (
string.IsNullOrEmpty(FriendlyName))
831 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: No friendly name provided.",
true, Legal,
EDaler);
835 if (
string.IsNullOrEmpty(Category))
837 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: No category provided.",
true, Legal,
EDaler);
841 if (
string.IsNullOrEmpty(Description))
843 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: No description provided.",
true, Legal,
EDaler);
847 if (Glyph is
null ||
string.IsNullOrEmpty(GlyphContentType) ||
848 !GlyphWidth.HasValue || !GlyphHeight.HasValue || GlyphWidth <= 0 || GlyphHeight <= 0)
850 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: A valid glyph has not been provided.",
true, Legal,
EDaler);
869 if (!(CertifierIds is
null))
871 int i, c = CertifierIds.
Length;
873 for (i = 0; i < c; i++)
875 if (
Signature.LegalId == CertifierIds[i])
883 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Owner JID not accessible.",
true, Legal,
EDaler);
889 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Creator JID not accessible.",
true, Legal,
EDaler);
893 if (!(CertifierIds is
null))
895 int i, c = CertifierIds.
Length;
897 for (i = 0; i < c; i++)
901 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Certifier JID not accessible.",
true, Legal,
EDaler);
907 List<Token> Tokens =
new List<Token>();
908 Dictionary<StateMachine, Token> StateMachines =
null;
910 DateTime
Created = DateTime.UtcNow;
911 StringBuilder sb =
new StringBuilder();
915 string NormalizedDefinition = sb.ToString();
917 Contract SingletonStateMachineContract =
null;
920 foreach (TokenIDReference TokenID
in AllTokenIDs)
924 if (TagReferences is
null)
925 TagReferences2 =
null;
929 TagReferences.Values.CopyTo(TagReferences2, 0);
935 TokenId = TokenID.TokenId.
ToString() +
"@" +
EDaler.MainDomain.Address,
937 BatchSize = AllTokenIDs.Count,
940 CreatorJid = CreatorJid,
945 Definition = NormalizedDefinition,
946 DefinitionNamespace = Definition.NamespaceURI,
947 DefinitionSchemaDigest = DefinitionSchema.Digest,
948 DefinitionSchemaHashFunction = DefinitionSchema.Algorithm,
949 Tags = TagReferences2,
951 CreatorCanDestroy = CreatorCanDestroy,
952 OwnerCanDestroyBatch = OwnerCanDestroyBatch,
953 OwnerCanDestroyIndividual = OwnerCanDestroyIndividual,
954 CertifierCanDestroy = CertifierCanDestroy,
955 ArchiveRequired =
Contract.ArchiveRequired,
956 ArchiveOptional =
Contract.ArchiveOptional,
961 Reference = Reference,
962 Valuator = ValuatorIds,
963 Assessor = AssessorIds,
964 Certifier = CertifierIds,
965 CertifierJids = CertifierJids,
966 Witness = WitnessIds,
969 FriendlyName = FriendlyName,
971 Description = Description,
973 GlyphContentType = GlyphContentType,
974 GlyphWidth = GlyphWidth.Value,
975 GlyphHeight = GlyphHeight.Value
978 TokenID.Token =
Token;
982 if (!(TagReferences2 is
null))
984 Dictionary<string, bool> TagNames =
new Dictionary<string, bool>();
987 TagNames[Ref.
Name] =
true;
989 LinkedList<XmlElement> ToCheck =
new LinkedList<XmlElement>();
991 ToCheck.AddLast(Definition);
993 while (!(ToCheck.First is
null))
995 XmlElement E = ToCheck.First.Value;
996 ToCheck.RemoveFirst();
998 foreach (XmlAttribute Attr
in E.Attributes)
999 TagNames.Remove(Attr.Value);
1001 TagNames.Remove(E.InnerText);
1003 foreach (XmlNode N
in E.ChildNodes)
1005 if (N is XmlElement E2)
1006 ToCheck.AddLast(E2);
1010 if (TagNames.Count > 0)
1012 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Uniqueness requires all tags to be referenced by the machine-readable XML definition of the token, either in attributes or element values.",
true, Legal,
EDaler);
1020 Token.ShortId = CalcShortId(
Token.
TokenId, TokenID.ShortIdLength, TokenID.ShortIdAlphabet);
1032 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Not able to parse State-Machine definition.",
true, Legal,
EDaler);
1036 catch (Exception ex)
1038 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Exception occurred when parsing state-machine definition: " + ex.Message +
"\r\n\r\n" + ex.StackTrace,
true, Legal,
EDaler);
1063 while (!(Temp is
null));
1065 StateMachine.StateMachineId = Id;
1072 if (SingletonStateMachine is
null)
1078 if (SingletonStateMachine is
null)
1084 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Attempted to change the definition of a singleton State-Machine.",
true, Legal,
EDaler);
1090 if (SingletonStateMachineContract is
null)
1092 SingletonStateMachineContract = await legal.GetContract(SingletonStateMachineContract.
ContractId);
1093 if (SingletonStateMachineContract is
null)
1095 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Unable to access original creation contract.",
true, Legal,
EDaler);
1099 if (SingletonStateMachineContract.State !=
ContractState.Signed)
1101 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Original creation contract not in a signed state.",
true, Legal,
EDaler);
1105 Dictionary<string, string> Parts =
new Dictionary<string, string>();
1107 if (!(SingletonStateMachineContract.ClientSignatures is
null))
1113 if (!(
Contract.ClientSignatures is
null))
1122 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Role mismatch compared to original creation contract, for part " +
Signature.LegalId,
true, Legal,
EDaler);
1130 if (Parts.Count > 0)
1132 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: All parts of the original creation contract need to sign the new contract.",
true, Legal,
EDaler);
1142 if (StateMachines is
null)
1143 StateMachines =
new Dictionary<StateMachine, Token>();
1161 foreach (TokenIDReference TokenID
in AllTokenIDs)
1163 Token Prev = await GetToken(TokenID.Token.TokenId,
false);
1164 Token PrevShort = await GetToken(TokenID.Token.ShortId,
false);
1166 if (!(Prev is
null) || !(PrevShort is
null))
1172 TokenID.TokenId = Guid.NewGuid();
1173 TokenID.Token.TokenId = TokenID.TokenId.ToString() +
"@" +
EDaler.MainDomain.Address;
1174 TokenID.Token.ShortId = CalcShortId(TokenID.Token.TokenId, TokenID.ShortIdLength, TokenID.ShortIdAlphabet);
1176 Prev = await GetToken(TokenID.Token.TokenId,
false);
1177 PrevShort = await GetToken(TokenID.Token.ShortId,
false);
1179 while (!(Prev is
null) || !(PrevShort is
null));
1183 if (!(Prev is
null))
1184 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Token with same ID already exists.",
true, Legal,
EDaler);
1186 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Token with same short ID already exists.",
true, Legal,
EDaler);
1198 TransactionId = Guid.NewGuid();
1200 decimal Commission = Value.Value * AllTokenIDs.Count * CommissionPercent.Value * 0.01m;
1205 string PaymentUri =
PaiwiseProcessor.GenerateContractualPaymentUri(TransactionId,
1206 CommissionPaidBy == CommissionPaidBy.Creator ? CreatorId : OwnerId,
true,
1212 await RejectContract(
Contract, ContractIsLocked,
"Unable to process payment for token creation. Tokens not created.",
1213 true, Legal,
EDaler,
"TokenPayment",
1214 new KeyValuePair<string, object>(
"Creator", CreatorId),
1215 new KeyValuePair<string, object>(
"Owner", OwnerId),
1216 new KeyValuePair<string, object>(
"Value", Value),
1217 new KeyValuePair<string, object>(
"Commission", Commission),
1218 new KeyValuePair<string, object>(
"Currency", Currency));
1226 if (!(StateMachines is
null))
1229 if (!(TagReferences is
null) && TagReferences.Count > 0)
1233 List<TokenTag> Tags =
new List<TokenTag>();
1243 catch (Exception ex)
1251 List<TokenEvent> Events =
new List<TokenEvent>();
1266 Timestamp = DateTime.UtcNow,
1273 catch (Exception ex)
1286 if (!(StateMachines is
null))
1288 foreach (KeyValuePair<StateMachine, Token> P
in StateMachines)
1294 StringBuilder Xml =
new StringBuilder();
1300 Xml.Append(
"<tokenAdded xmlns='");
1304 Xml.Append(
"</tokenAdded>");
1306 if (await SendTokenMessage(
EDaler, Xml.ToString(), OwnerJid,
true,
true))
1307 await TokenAdded(
Token, OwnerJid);
1324 internal static Task<bool> SendTokenMessage(
EDalerComponent EDaler,
string Xml,
string RecipientJid,
bool ToClient,
bool ToBroker)
1326 return SendTokenMessage(
EDaler, Xml,
new XmppAddress(RecipientJid), ToClient, ToBroker);
1343 await
EDaler.Server.SendMessage(
string.Empty,
string.Empty,
EDaler.MainDomain, Recipient,
1347 if (
EDaler.Server.IsServerDomain(Recipient.
Domain,
true))
1362 private static string CalcShortId(
string TokenId,
int ShortIdLength,
string ShortIdAlphabet)
1364 if (ShortIdLength <= 0)
1365 return string.Empty;
1368 int i, j, c = Bin.Length;
1370 for (i = 4, j = 0; i < c; i++, j = (j + 1) & 3)
1373 int Seed = BitConverter.ToInt32(Bin, 0);
1374 Random Rnd =
new Random(Seed);
1375 char[] ch =
new char[ShortIdLength];
1377 c = ShortIdAlphabet.Length;
1379 return string.Empty;
1381 for (i = 0; i < ShortIdLength; i++)
1382 ch[i] = ShortIdAlphabet[Rnd.Next(c)];
1384 return new string(ch);
1393 Dictionary<string, object> Counts =
new Dictionary<string, object>();
1395 StringBuilder Xml =
new StringBuilder();
1401 Xml.Append(
"<tokenAdded xmlns='");
1405 Xml.Append(
"</tokenAdded>");
1409 if (await SendTokenMessage(eDaler, Xml.ToString(), Owner,
false,
true))
1415 Inc(Counts, Owner.
Domain);
1427 Dictionary<string, object> Counts =
new Dictionary<string, object>();
1433 Inc(Counts, Owner.
Domain);
1439 private static void Inc(Dictionary<string, object> Counts,
string Key)
1441 if (Counts.TryGetValue(Key, out
object Obj) && Obj is
int Count)
1442 Counts[Key] = Count + 1;
1449 #region Destroy Contract
1451 private static async Task<bool> DestroyTokens(XmlElement Destroy,
Contract Contract,
bool ContractIsLocked,
string TrustProviderRole,
LegalComponent Legal,
1454 List<string> TokenIDs =
new List<string>();
1456 foreach (XmlElement E
in Destroy.ChildNodes)
1458 if (E.NamespaceURI ==
Contract.ForMachinesNamespace)
1460 switch (E.LocalName)
1466 TokenIDs.Add(TokenId);
1472 if (TokenIDs.Count == 0)
1474 await RejectContract(
Contract, ContractIsLocked,
"Rejected token destruction contract: No Token IDs.",
true, Legal,
EDaler);
1478 Dictionary<string, KeyValuePair<string, Token>> AuthorizedBy =
new Dictionary<string, KeyValuePair<string, Token>>();
1479 Dictionary<string, KeyValuePair<string, List<Token>>> TokensPerBatch =
new Dictionary<string, KeyValuePair<string, List<Token>>>();
1480 List<Token> Tokens =
new List<Token>();
1485 foreach (
string TokenID
in TokenIDs)
1487 Token Token = await GetToken(TokenID,
false);
1491 await RejectContract(
Contract, ContractIsLocked,
"Rejected token destruction contract: Token referenced that does not exist.",
true, Legal,
EDaler);
1494 else if (!
Contract.Duration.HasValue ||
1497 await RejectContract(
Contract, ContractIsLocked,
"Rejected token destruction contract: Duration must cover token expiry date.",
true, Legal,
EDaler);
1502 if (!(
Contract.ClientSignatures is
null))
1511 AuthorizedBy[TokenID] =
new KeyValuePair<string, Token>(
Signature.LegalId,
Token);
1521 AuthorizedBy[TokenID] =
new KeyValuePair<string, Token>(
Signature.LegalId,
Token);
1526 if (!TokensPerBatch.TryGetValue(
Token.
CreationContract, out KeyValuePair<
string, List<Token>> TokensInBatch))
1528 TokensInBatch =
new KeyValuePair<string, List<Token>>(
Signature.LegalId,
new List<Token>());
1532 TokensInBatch.Value.Add(
Token);
1540 for (i = 0; i < c; i++)
1547 AuthorizedBy[TokenID] =
new KeyValuePair<string, Token>(
Signature.LegalId,
Token);
1558 if (TokensPerBatch.Count > 0)
1560 foreach (KeyValuePair<
string, List<Token>> TokensInBatch
in TokensPerBatch.Values)
1562 if (TokensInBatch.Value[0].BatchSize == TokensInBatch.Value.Count)
1565 AuthorizedBy[
Token.
TokenId] =
new KeyValuePair<string, Token>(TokensInBatch.Key,
Token);
1570 if (AuthorizedBy.Count != TokenIDs.Count)
1572 await RejectContract(
Contract, ContractIsLocked,
"Rejected token destruction contract: Not authorized to destroy token referenced in contract.",
true, Legal,
EDaler);
1579 List<TokenEvent> Events =
new List<TokenEvent>();
1581 foreach (KeyValuePair<string, Token> P
in AuthorizedBy.Values)
1585 ArchiveOptional = P.
Value.ArchiveOptional,
1586 ArchiveRequired = P.Value.ArchiveRequired,
1587 Expires = P.Value.Expires,
1590 TokenId = P.
Value.TokenId,
1592 Currency =
string.Empty,
1593 Timestamp = DateTime.UtcNow,
1597 Tokens.Add(P.Value);
1604 await DeletePersonalEvents(TokenIDs);
1611 catch (Exception ex)
1631 foreach (KeyValuePair<string, Token> P
in AuthorizedBy.Values)
1635 StringBuilder Xml =
new StringBuilder();
1641 if (!
string.IsNullOrEmpty(PrevOwner))
1643 Token.Owner =
string.
Empty;
1644 Token.OwnerJid =
string.
Empty;
1650 Xml.Append(
"<tokenRemoved xmlns='");
1654 Xml.Append(
"</tokenRemoved>");
1656 if (await SendTokenMessage(
EDaler, Xml.ToString(), PrevOwner,
true,
true))
1657 await TokenRemoved(
Token, PrevOwner);
1666 await DeletePersonalEvents(
new string[] { Token.TokenId });
1678 Currency =
string.
Empty,
1679 Timestamp = DateTime.UtcNow,
1694 if (!
string.IsNullOrEmpty(PrevOwner))
1696 StringBuilder Xml =
new StringBuilder();
1698 Token.Owner =
string.Empty;
1699 Token.OwnerJid =
string.Empty;
1700 Token.OwnershipContract =
string.Empty;
1705 Xml.Append(
"<tokenRemoved xmlns='");
1709 Xml.Append(
"</tokenRemoved>");
1711 if (await SendTokenMessage(
EDaler, Xml.ToString(), PrevOwner,
true,
true))
1712 await TokenRemoved(
Token, PrevOwner);
1716 internal static async Task DeletePersonalEvents(IEnumerable<string> TokenIds)
1718 foreach (
string TokenId
in TokenIds)
1726 catch (Exception ex)
1735 #region Transfer Contract
1737 private static async Task<bool> TransferTokens(XmlElement Transfer,
Contract Contract,
bool ContractIsLocked,
string TrustProviderRole,
LegalComponent Legal,
1740 List<string> TokenIDs =
new List<string>();
1741 string Currency =
null;
1742 string OwnershipContract =
null;
1743 decimal? Value =
null;
1744 decimal? CommissionPercent =
null;
1746 foreach (XmlElement E
in Transfer.ChildNodes)
1748 if (E.NamespaceURI ==
Contract.ForMachinesNamespace)
1750 switch (E.LocalName)
1756 TokenIDs.Add(TokenId);
1762 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid value.",
true, Legal,
EDaler);
1772 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid currency.",
true, Legal,
EDaler);
1779 case "CommissionPercent":
1782 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid commission (%).",
true, Legal,
EDaler);
1786 CommissionPercent = d2;
1789 case "OwnershipContract":
1792 await RejectContract(
Contract, ContractIsLocked,
"Rejected token creation contract: Invalid Ownership contract reference.",
true, Legal,
EDaler);
1796 OwnershipContract = s2;
1802 if (TokenIDs.Count == 0)
1804 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: No Token IDs.",
true, Legal,
EDaler);
1808 if (!Value.HasValue || Value.Value <= 0)
1810 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Value must be positive.",
true, Legal,
EDaler);
1814 if (
string.IsNullOrEmpty(Currency) || Currency.Length != 3)
1816 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Invalid currency.",
true, Legal,
EDaler);
1820 if (!CommissionPercent.HasValue)
1822 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Commission missing.",
true, Legal,
EDaler);
1828 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Commission too low.",
true, Legal,
EDaler);
1832 List<Token> Tokens =
new List<Token>();
1841 foreach (
string TokenID
in TokenIDs)
1843 Token Token = await GetToken(TokenID,
false);
1847 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Token referenced that does not exist.",
true, Legal,
EDaler);
1852 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Incorrect ownership contract reference.",
true, Legal,
EDaler);
1855 else if (!
Contract.Duration.HasValue ||
1858 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Duration must cover token expiry date.",
true, Legal,
EDaler);
1863 if (!(
Contract.ClientSignatures is
null))
1867 bool Identified =
false;
1878 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Multiple sellers in one contract not permitted.",
true, Legal,
EDaler);
1892 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Token not hosted by this trust provider.",
true, Legal,
EDaler);
1898 else if (TrustProviderId !=
Signature.LegalId)
1900 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Multiple trust providers in one contract not permitted.",
true, Legal,
EDaler);
1916 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Only one buyer allowed (buyer=not current owner or trust provider).",
true, Legal,
EDaler);
1924 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: No seller identified for token.",
true, Legal,
EDaler);
1930 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: No buyer identified for token.",
true, Legal,
EDaler);
1936 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Trust provider already signed.",
true, Legal,
EDaler);
1945 if (Tokens.Count != TokenIDs.Count)
1947 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Not authorized to transfer token referenced in contract.",
true, Legal,
EDaler);
1951 if (SellerJid == BuyerJid)
1953 await RejectContract(
Contract, ContractIsLocked,
"Rejected token transfer contract: Buyer and Seller cannot be the same.",
true, Legal,
EDaler);
1962 TransactionId = Guid.NewGuid();
1964 decimal Total = Value.Value * TokenIDs.Count;
1965 decimal Commission = Total * CommissionPercent.Value * 0.01m;
1968 string PaymentUri1 =
PaiwiseProcessor.GenerateContractualPaymentUri(TransactionId, BuyerId,
true,
1969 SellerId,
true, Currency, Total,
null, Ref,
Contract.
ContractId,
null, 1, out _, out _);
1973 await RejectContract(
Contract, ContractIsLocked,
"Unable to process payment for token transfer. Tokens not created.",
1974 true, Legal,
EDaler,
"TokenPayment",
1975 new KeyValuePair<string, object>(
"Buyer", BuyerId.
Value),
1976 new KeyValuePair<string, object>(
"Seller", SellerId.
Value),
1977 new KeyValuePair<string, object>(
"Value", Value),
1978 new KeyValuePair<string, object>(
"Commission", Commission),
1979 new KeyValuePair<string, object>(
"Currency", Currency));
1986 string PaymentUri2 =
PaiwiseProcessor.GenerateContractualPaymentUri(Guid.NewGuid(), SellerId,
true,
1992 await RejectContract(
Contract, ContractIsLocked,
"Unable to process commission payment for token transfer.",
1993 false, Legal,
EDaler,
"TokenPayment",
1994 new KeyValuePair<string, object>(
"Buyer", BuyerId.
Value),
1995 new KeyValuePair<string, object>(
"Seller", SellerId.
Value),
1996 new KeyValuePair<string, object>(
"Value", Value),
1997 new KeyValuePair<string, object>(
"Commission", Commission),
1998 new KeyValuePair<string, object>(
"Currency", Currency));
2002 List<TokenEvent> Events =
new List<TokenEvent>();
2006 Token.Value = Value.Value;
2007 Token.Currency = Currency;
2008 Token.Owner = BuyerId;
2009 Token.OwnerJid = BuyerJid;
2021 Value = Value.
Value,
2022 Commission = Commission,
2023 Currency = Currency,
2025 Timestamp = DateTime.UtcNow,
2033 await DeletePersonalEvents(TokenIDs);
2040 catch (Exception ex)
2052 int c = Tokens.Count;
2054 for (i = 0; i < c; i++)
2060 catch (Exception ex)
2067 StringBuilder Xml =
new StringBuilder();
2073 Xml.Append(
"<tokenRemoved xmlns='");
2077 Xml.Append(
"</tokenRemoved>");
2079 if (await SendTokenMessage(
EDaler, Xml.ToString(), SellerJid,
true,
true))
2080 await TokenRemoved(
Token, SellerJid);
2084 Xml.Append(
"<tokenAdded xmlns='");
2088 Xml.Append(
"</tokenAdded>");
2090 if (await SendTokenMessage(
EDaler, Xml.ToString(), BuyerJid,
true,
true))
2091 await TokenAdded(
Token, BuyerJid);
2101 #region XMPP interface
2164 private static async Task GetTokenHandler(
object Sender,
IqEventArgs e)
2170 StringBuilder Xml =
new StringBuilder();
2176 private static async Task<Token> GetToken(
IqEventArgs e)
2180 Token Token = await GetToken(TokenId,
false);
2187 if (!await IsAuthorizedAccess(
Token, e))
2233 private static async Task GetTokensHandler(
object Sender,
IqEventArgs e)
2244 Xml = SerializeTokenReferences(TokenReferences);
2247 List<Token> Tokens =
new List<Token>();
2252 if (!(
Token is
null))
2256 Xml = SerializeTokenReferences(Tokens);
2262 private static async Task GetContractTokensHandler(
object Sender,
IqEventArgs e)
2295 List<TokenReference> TokenReferences =
new List<TokenReference>();
2301 TokenId = Token.TokenId
2305 Xml = SerializeTokenReferences(TokenReferences);
2308 Xml = SerializeTokenReferences(Tokens);
2313 internal static string SerializeTokenReferences(IEnumerable<TokenReference> Tokens)
2315 StringBuilder Xml =
new StringBuilder();
2317 Xml.Append(
"<tokenReferences xmlns='");
2323 Xml.Append(
"<ref id='");
2328 Xml.Append(
"</tokenReferences>");
2330 return Xml.ToString();
2333 internal static string SerializeTokenReferences(IEnumerable<Token> Tokens)
2335 StringBuilder Xml =
new StringBuilder();
2337 Xml.Append(
"<tokens xmlns='");
2344 Xml.Append(
"</tokens>");
2346 return Xml.ToString();
2353 private static async Task GetTotalsHandler(
object Sender,
IqEventArgs e)
2355 StringBuilder Xml =
new StringBuilder();
2356 string Currency =
null;
2360 Xml.Append(
"<totals xmlns='");
2366 if (Currency is
null || Currency != TokenRef.
Currency)
2370 Xml.Append(
"<total nr='");
2371 Xml.Append(Nr.ToString());
2372 Xml.Append(
"' total='");
2374 Xml.Append(
"' currency='");
2380 Total = TokenRef.
Value;
2386 Total += TokenRef.
Value;
2392 Xml.Append(
"<total nr='");
2393 Xml.Append(Nr.ToString());
2394 Xml.Append(
"' total='");
2396 Xml.Append(
"' currency='");
2401 Xml.Append(
"</totals>");
2410 private static async Task SetNoteTextHandler(
object Sender,
IqEventArgs e)
2415 Token Token = await GetToken(TokenId,
false);
2431 Note = e.
Query.InnerText,
2432 Personal = Personal,
2433 Timestamp = DateTime.UtcNow,
2434 TokenId = Token.TokenId
2439 if (!await IsApprovedExternalSource(
Token, e))
2447 Note = e.
Query.InnerText,
2448 Personal = Personal,
2449 Timestamp = DateTime.UtcNow,
2451 Source = e.From.BareJid
2458 await Task.Run(async () =>
2464 catch (Exception ex)
2479 if (Machine is
null)
2485 if (Machine.CurrentState is
null)
2491 if (Machine.CurrentState.HasEnded)
2497 if (!Machine.CurrentState.ContainsSource(e.
From.
BareJid))
2499 await e.
IqErrorForbidden(e.
To,
"You are not an approved external part for this token.",
"en");
2505 await e.
IqErrorForbidden(e.
To,
"You are not an approved external part for this token.",
"en");
2516 private static async Task SetNoteXmlHandler(
object Sender,
IqEventArgs e)
2521 Token Token = await GetToken(TokenId,
false);
2531 string LocalName =
null;
2532 string Namespace =
null;
2534 foreach (XmlNode N
in e.
Query.ChildNodes)
2536 if (N is XmlElement E)
2540 Namespace = E.NamespaceURI;
2553 if (!(legal is
null))
2555 XmlDocument Doc =
new XmlDocument()
2557 PreserveWhitespace =
true
2561 (string, Dictionary<string, ValidationSchema>) P = await legal.ValidateContent(Doc);
2562 if (!
string.IsNullOrEmpty(P.Item1))
2576 Personal = Personal,
2577 Timestamp = DateTime.UtcNow,
2580 LocalName = LocalName,
2581 Namespace = Namespace
2586 if (!await IsApprovedExternalSource(
Token, e))
2594 Personal = Personal,
2595 Timestamp = DateTime.UtcNow,
2598 LocalName = LocalName,
2599 Namespace = Namespace,
2600 Source = e.From.BareJid
2607 await Task.Run(async () =>
2613 catch (Exception ex)
2624 private static async Task GetEventsHandler(
object Sender,
IqEventArgs e)
2628 Token Token = await GetToken(TokenId,
false);
2635 if (!await IsAuthorizedAccess(
Token, e))
2641 IEnumerable<TokenEvent> Events = await GetTokenEvents(
Token, Offset, MaxCount);
2642 StringBuilder Xml =
new StringBuilder();
2644 Xml.Append(
"<events xmlns='");
2649 Event.Serialize(Xml);
2651 Xml.Append(
"</events>");
2656 internal static async Task<IEnumerable<TokenEvent>> GetTokenEvents(
Token Token,
int Offset,
int MaxCount)
2667 IEnumerator<TokenEvent> e1 = Events.GetEnumerator();
2668 IEnumerator<TokenEvent> e2 = Events2.GetEnumerator();
2670 LinkedList<TokenEvent> Merged =
new LinkedList<TokenEvent>();
2671 bool Has1 = e1.MoveNext();
2672 bool Has2 = e2.MoveNext();
2674 while (Has1 && Has2)
2676 if (e1.Current.Timestamp > e2.Current.Timestamp)
2678 Merged.AddLast(e1.Current);
2679 Has1 = e1.MoveNext();
2683 Merged.AddLast(e2.Current);
2684 Has2 = e2.MoveNext();
2690 Merged.AddLast(e1.Current);
2691 Has1 = e1.MoveNext();
2696 Merged.AddLast(e2.Current);
2697 Has2 = e2.MoveNext();
2708 #region GetCreationAttributes
2710 private static async Task GetCreationAttributesHandler(
object Sender,
IqEventArgs e)
2712 StringBuilder Xml =
new StringBuilder();
2714 Xml.Append(
"<creationAttributes xmlns='");
2716 Xml.Append(
"' currency='");
2718 if (!(eDaler is
null))
2721 Xml.Append(
"' commission='");
2723 Xml.Append(
"' trustProvider='");
2735 #region GetDescription
2737 private static async Task GetDescriptionHandler(
object Sender,
IqEventArgs e)
2744 StringBuilder Xml =
new StringBuilder();
2746 Xml.Append(
"<report xmlns='");
2750 Xml.Append(
"</report>");
2768 internal static async Task<string> FormatReport(
string Markdown,
2773 AllowScriptTag =
false,
2774 AudioAutoplay =
false,
2775 AudioControls =
false,
2777 ParseMetaData =
false,
2779 VideoAutoplay =
false,
2780 VideoControls =
false,
2781 EmbedEmojis =
false,
2786 return Task.FromResult(Prohibited);
2805 return FixLocalFileLinks(await Doc.GenerateXAML());
2808 return FixLocalFileLinks(await Doc.GenerateXamarinForms());
2811 return FixLocalFileLinks(await Doc.GenerateSmartContractXml());
2814 throw new ArgumentException(
"Unrecognized report format: " + Format.ToString(), nameof(Format));
2818 private static string FixLocalFileLinks(
string Report)
2820 if (localFileReference is
null)
2823 if (
string.IsNullOrEmpty(s))
2826 if (!
string.IsNullOrEmpty(s) && s[s.Length - 1] == Path.DirectorySeparatorChar)
2827 s = s.Substring(0, s.Length - 1);
2829 localFileReference =
new Regex(
"[\"']" + s.Replace(
"\\",
"\\\\") +
2830 "(?'LocalUrl'[^\"']*)[\"']", RegexOptions.Compiled | RegexOptions.Multiline);
2833 StringBuilder sb =
new StringBuilder();
2835 int c = Report.Length;
2839 Match M = localFileReference.Match(Report, i);
2842 sb.Append(Report.Substring(i, c - i));
2847 sb.Append(Report.Substring(i, M.Index));
2848 i = M.Index + M.Length;
2851 sb.Append(
Gateway.
GetUrl(M.Groups[
"LocalUrl"].Value.Replace(Path.DirectorySeparatorChar,
'/')));
2856 return sb.ToString();
2859 private static Regex localFileReference =
null;
2865 private static async Task TokenAddedIqHandler(
object Sender,
IqEventArgs e)
2867 string Error =
null;
2870 foreach (XmlNode N
in e.
Query.ChildNodes)
2872 if (N is XmlElement E)
2876 Token Token = IsTokenMessageElement(E, e.
From, out
string Message);
2877 if (!(
Token is
null))
2879 else if (!
string.IsNullOrEmpty(Message))
2884 if (!
string.IsNullOrEmpty(Error))
2892 private static async Task TokenAddedMessageHandler(
object Sender,
MessageEventArgs e)
2894 foreach (XmlNode N
in e.
Content.ChildNodes)
2896 if (N is XmlElement E)
2899 if (!(
Token is
null))
2918 OwnerJid = OwnerJid,
2922 Currency = Token.Currency
2933 Ref.OwnerJid = OwnerJid;
2942 private static Token IsTokenMessageElement(XmlElement E,
XmppAddress From, out
string Message)
2946 Message =
"Non-token embedded element.";
2952 Message =
"Unable to parse embedded token.";
2958 Message =
"Embedded token discarded. Owner not on broker.";
2964 Message =
"Embedded token discarded. Sender not host of token.";
2969 return EmbeddedToken;
2974 #region Token Removed
2976 private static async Task TokenRemovedIqHandler(
object Sender,
IqEventArgs e)
2978 string Error =
null;
2981 foreach (XmlNode N
in e.
Query.ChildNodes)
2983 if (N is XmlElement E)
2987 Token Token = IsTokenMessageElement(E, e.
From, out
string Message);
2988 if (!(
Token is
null))
2990 else if (!
string.IsNullOrEmpty(Message))
2995 if (!
string.IsNullOrEmpty(Error))
3003 private static async Task TokenRemovedMessageHandler(
object Sender,
MessageEventArgs e)
3005 foreach (XmlNode N
in e.
Content.ChildNodes)
3007 if (N is XmlElement E)
3010 if (!(
Token is
null))
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
Static class managing encoding and decoding of internet content.
static Task< object > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
Contains a markdown document. This markdown document class supports original markdown,...
Task< string > GenerateMarkdown()
Generates Markdown from the markdown text.
async Task< string > GeneratePlainText()
Generates Plain Text from the markdown text.
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
Class representing an event.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
Static class managing the runtime environment of the IoT Gateway.
static string GetUrl(string LocalResource)
Gets a URL for a resource.
static ContractsClient ContractsClient
XMPP Contracts Client, if such a compoent is available on the XMPP broker.
static string RootFolder
Web root folder.
Configures legal identity for the gateway.
static bool IsMeApproved(CaseInsensitiveString LegalId)
Checks if a Legal Identity refers to an approved ID of the gateway.
static bool HasApprovedLegalIdentities
If there are approved legal identities configured.
static string LatestApprovedLegalIdentityId
Latest approved Legal Identity ID.
Implements an HTTP server.
static Variables CreateVariables()
Creates a new collection of variables, that contains access to the global set of variables.
Base class for components.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
XmppAddress MainDomain
Main/principal domain address
bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the component domain, or optionally, an alternative component domain.
XmppServer Server
XMPP Server.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
Event arguments for IQ queries.
XmppAddress From
From address attribute
Task IqResult(string Xml, string From)
Returns a response to the current request.
Task IqErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns a item-not-found error.
XmlElement Query
Query element, if found, null otherwise.
XmppAddress To
To address attribute
Task IqErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Returns a service-unavailable error.
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
Event arguments for responses to IQ queries.
XmlElement FirstElement
First child element of the Response element.
bool Ok
If the response is an OK result response (true), or an error response (false).
Event arguments for Messages.
XmppAddress From
From address attribute
XmlElement Content
Content element, if found, null otherwise.
Contains information about one XMPP address.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
CaseInsensitiveString BareJid
Bare JID
Task< IqResultEventArgs > IqRequest(string Type, string From, string To, string Language, string ContentXml)
Sends an IQ stanza to a recipient.
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
CaseInsensitiveString Domain
Domain name.
static bool CheckExpressionSafe(Expression Expression, out ScriptNode Prohibited)
Checks if an expression is safe to execute (if it comes from an external source).
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
int Length
Gets the number of characters in the current CaseInsensitiveString object.
string LowerCase
Lower-case representation of the case-insensitive string.
int IndexOf(CaseInsensitiveString value, StringComparison comparisonType)
Reports the zero-based index of the first occurrence of the specified string in the current System....
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
override string ToString()
CaseInsensitiveString Substring(int startIndex, int length)
Retrieves a substring from this instance. The substring starts at a specified character position and ...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static Task EndBulk()
Ends bulk-processing of data. Must be called once for every call to StartBulk.
static Task StartBulk()
Starts bulk-proccessing of data. Must be followed by a call to EndBulk.
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field lesser than a given value.
Implements an in-memory cache.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
async void Dispose()
Disposes of the named semaphore, and releases any locks the object manages.
Static class of application-wide semaphores that can be used to order access to editable objects.
static async Task< Semaphore > BeginRead(string Key)
Waits until the semaphore identified by Key is ready for reading. Each call to BeginRead must be fol...
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Base class for all nodes in a parsed script tree.
Contains methods for simple hash calculations.
static byte[] ComputeSHA256Hash(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
Manages eDaler on accounts connected to the broker.
async Task< string > GetDefaultCurrency()
Gets the default currency
Represents a digital signature on a contract.
Contains the definition of a contract
static void NormalizeXml(XmlElement Xml, StringBuilder Output, string CurrentNamespace)
Normalizes an XML element.
CaseInsensitiveString ContractId
Contract Identity
Task< bool > CanRead(XmppAddress Jid, XmppServer Server, LegalComponent LegalComponent)
Checks if a client with a given Jid is allowed to read the contract.
Class defining a part in a contract
CaseInsensitiveString Role
Role of the part in the contract
CaseInsensitiveString LegalId
Legal identity of part
int MinCount
Smallest amount of signatures of this role required for a legally binding contract.
bool CanRevoke
If parts having this role, can revoke their signature, once signed.
int MaxCount
Largest amount of signatures of this role required for a legally binding contract.
CaseInsensitiveString Name
Name of the role.
Contains an XML schema reference, used to validate a contract.
Abstract base class of signatures
Provisioning and registry service component.
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
Event raised when a token has been created.
Event raised when a token has been destroyed.
A text note logged on the token from an external source.
An xml note logged on the token from an external source.
A text note logged on the token.
An xml note logged on the token.
string LocalName
Local name of root-element in XML
Abstract base class for token events.
Abstract base class for token events containing notes made by the owner.
decimal Value
Latest value of token
Event raised when a token has been transferred.
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
static async Task< Dictionary< string, object > > TokenOwnerStatistics()
Reindexes token references, and sends relevant token messages to remote neurons.
const string NeuroFeaturesNamespace
https://paiwise.tagroot.io/Schema/NeuroFeatures.xsd
static async Task< Dictionary< string, object > > ReindexTokenReferences()
Reindexes token references, and sends relevant token messages to remote neurons.
Boolean-valued token tag.
DateTime-valued token tag.
Duration-valued token tag.
TimeSpan-valued token tag.
Abstract base class for token tag references.
abstract object Value
Object value.
CaseInsensitiveString Name
Tag Name
abstract TokenTag CreateTag(Token Token)
Creates a Tag object.
CaseInsensitiveString CreatorJid
JID of Creator of token
bool HasStateMachine
If the token has an associated state-machine.
Duration? ArchiveOptional
Duration after which token expires, and the required archiving time, the token can optionally be arch...
Guid ComputeUniqueGuid()
Computes a GUID from the defining contents of the token.
string Definition
M2M definition of token, in XML, from the original creation contract.
bool OwnerCanDestroyBatch
If the current owner is allowed to destroy the token.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeServerSignature)
Serializes the Token, in normalized form.
CaseInsensitiveString OwnershipContract
ID of contract that details the claims of the current owner
ContractVisibility Visibility
Visibility of token
string DefinitionNamespace
Namespace of M2M definition of token.
CaseInsensitiveString Owner
Current owner of token
CaseInsensitiveString OwnerJid
JID of Current owner of token
CaseInsensitiveString TrustProviderJid
JID of Trust Provider, asserting claims in the token.
CaseInsensitiveString CreationContract
ID of contract that details the creation of the token.
bool IsExternalPart(CaseInsensitiveString BareJid)
Checks if a JID is an external part in the creation of the contract.
bool CertifierCanDestroy
If a certifier is allowed to destroy the token.
CaseInsensitiveString ShortId
Short ID
CaseInsensitiveString[] CertifierJids
Optional Bare JIDs of parties used to certify claims in the legal document used to create the token.
TokenTagReference[] Tags
Optional tags and their values, attached on created.
DateTime Updated
When token was updated.
string Description
Description Markdown for the token.
Duration? ArchiveRequired
Duration after which token expires, the token is required to be archived.
static bool TryParse(XmlElement Xml, out Token Token)
Serializes the Token, in normalized form.
DateTime Created
When token was created.
bool CreatorCanDestroy
If the creator is allowed to destroy the token.
decimal Value
Latest value of token
CaseInsensitiveString[] Certifier
Optional Legal IDs of parties used to certify claims in the legal document used to create the token.
CaseInsensitiveString MachineId
State Machine ID, if any
string Currency
Currency used to represent latest value.
CaseInsensitiveString TrustProvider
Trust Provider, asserting claims in the token.
DateTime Expires
Expiry date of token.
bool OwnerCanDestroyIndividual
If the current owner is allowed to destroy the token.
CaseInsensitiveString TokenId
Token ID
CaseInsensitiveString Creator
Creator of token
Contains a reference to a token, possibly on another neuron.
CaseInsensitiveString TokenId
Token ID
decimal Value
Latest value of token
string Currency
Currency used to represent latest value.
CaseInsensitiveString OwnerJid
JID of Current owner of token
DateTime Updated
When token was updated.
Paiwise processor, processing payment instructions defined in smart contracts.
Class representing a state machine.
string XmlDefinition
XML Definition.
CaseInsensitiveString StateMachineId
ID of State Machine.
CaseInsensitiveString DefinitionContractId
ID of Definition Contract
static StateMachine Parse(Token Token)
Parses the XML representation of a State Machine.
const string StateMachineNamespace
https://paiwise.tagroot.io/Schema/StateMachines.xsd
Component that synchronizes content in the federated network, by sending synchronization messages and...
static async Task SendMessage(CaseInsensitiveString Sender, CaseInsensitiveString Recipient, CaseInsensitiveString RecipientServer, string Xml)
Sends a synchronization message
delegate Task< ScriptNode > AuthorizeExpression(Expression Expression)
Delegate for expression authorization methods.
ContractState
Recognized contract states
ContractVisibility
Visibility types for contracts.
ReportFormat
Desired report format
TokenIdMethod
By which mechanism the Token ID was created
Represents a duration value, as defined by the xsd:duration data type: http://www....