3using System.Collections.Generic;
4using System.Threading.Tasks;
23 private decimal amount = 0;
24 private bool transferred =
false;
25 private DateTime prevTP = DateTime.MinValue;
27 private readonly
bool validateSenderSignature;
37 this.validateSenderSignature = ValidateSenderSignature;
46 if (this.validateSenderSignature)
54 this.Uri.From,
this.Uri.State,
this.Uri.Created,
55 this.Uri.PreSign,
this.Uri.Signature,
null);
65 string JidDomain = i < 0 ? this.Uri.EDaler.Server.Domain : TempAddress.
Domain.
Substring(i + 1);
74 if (Signer.Id != Temp.Id)
81 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.BadRequest,
"Invalid signature.",
false);
86 if (!await base.DoPrepare())
91 if (this.wallet is
null)
93 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.ServiceUnavailable,
"Wallet not found.",
false);
102 new CurrencyPair(this.wallet.Currency,
this.Uri.Currency));
104 if (Converter is
null)
106 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.Forbidden,
"Cannot reserve eDaler in " +
this.Uri.Currency +
". No currency conversion service available.",
false);
113 if (this.quote is
null)
115 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.Forbidden,
"Cannot reserve eDaler in " +
this.Uri.Currency +
". Conversion not supported by service.",
false);
121 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.Forbidden,
"Cannot reserve eDaler in " +
this.Uri.Currency +
". Currency converter reports: " + ex.Message,
false);
125 this.amount *= this.quote.
Rate;
130 if (this.wallet.Balance <
this.amount)
132 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.Forbidden,
"Lacks funds to perform reservation.",
false);
147 if (this.wallet.Balance <
this.amount)
149 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.Forbidden,
"Lacks funds to perform reservation.",
false);
153 if (!await base.DoExecute())
157 DateTime BakTP = this.wallet.BalanceTimestamp;
158 decimal Bak = this.wallet.Balance;
159 decimal ReservedBak = this.wallet.Reserved;
160 bool RefAdded =
false;
166 TransactionId = this.
Uri.
Id,
167 Timestamp = DateTime.UtcNow,
168 Account = this.wallet.Account,
171 Balance = this.wallet.Balance - this.amount,
172 Reserved = this.wallet.Reserved + this.amount,
174 EncryptionPublicKey = this.Uri.EncryptionPublicKey
180 this.prevTP = this.wallet.BalanceTimestamp;
182 this.wallet.Balance -= this.amount;
183 this.wallet.Reserved += this.amount;
184 this.wallet.BalanceTimestamp = Ref.Timestamp;
188 this.transferred =
true;
194 this.
Uri.
State.Error(Uris.States.EDalerUriErrorType.ServiceUnavailable,
"eDaler reservation could not be processed due to internal failure.",
false);
196 this.wallet.Balance = Bak;
197 this.wallet.Reserved = ReservedBak;
198 this.wallet.BalanceTimestamp = BakTP;
199 this.transferred =
false;
207 catch (Exception ex2)
228 if (!await base.DoCommit())
233 string Xml = await this.
Uri.
EDaler.GetWalletBalanceXml(this.wallet.Account, Domain,
this.@event);
247 protected override void LogEvent(
string To,
string From, decimal Amount,
string Currency,
248 KeyValuePair<string, object>[] Tags)
250 Append(ref Tags, this.quote);
252 Log.
Notice(Amount.ToString() +
" " + Currency +
" eDaler reserved in wallet.",
253 To, From,
"eDalerReserved",
EventLevel.Major, Tags);
258 if (!(Quote is
null))
261 Array.Resize(ref Tags, c + 5);
262 Tags[c] =
new KeyValuePair<string, object>(
"ExchangeFrom", Quote.
FromCurrency);
263 Tags[c + 1] =
new KeyValuePair<string, object>(
"ExchangeTo", Quote.
ToCurrency);
264 Tags[c + 2] =
new KeyValuePair<string, object>(
"ExchangeRate", Quote.
Rate);
265 Tags[c + 3] =
new KeyValuePair<string, object>(
"Timestamp", Quote.
Timestamp);
266 Tags[c + 4] =
new KeyValuePair<string, object>(
"Source", Quote.
Source);
280 if (this.amount != 0 && this.transferred)
282 DateTime BakTP = this.wallet.BalanceTimestamp;
283 decimal Bak = this.wallet.Balance;
284 decimal ReservedBak = this.wallet.Reserved;
288 this.wallet.Balance += this.amount;
289 this.wallet.Reserved -= this.amount;
291 if (this.wallet.BalanceTimestamp ==
this.@event.Timestamp)
292 this.wallet.BalanceTimestamp = this.prevTP;
296 this.transferred =
false;
302 this.wallet.Balance = Bak;
303 this.wallet.Reserved = ReservedBak;
304 this.wallet.BalanceTimestamp = BakTP;
306 KeyValuePair<string, object>[] Tags =
new KeyValuePair<string, object>[]
308 new KeyValuePair<string, object>(
"Amount", this.amount),
309 new KeyValuePair<string, object>(
"Currency", this.
Uri.
Currency),
310 new KeyValuePair<string, object>(
"RefId", this.
Uri.
Id.ToString()),
311 new KeyValuePair<string, object>(
"Sender", this.
Uri.
State.Sender.Value),
314 new KeyValuePair<string, object>(
"Uri", this.
Uri.
UriString)
317 Append(ref Tags, this.quote);
319 Log.
Error(
"Unable to rollback wallet reservation of " + this.amount.ToString() +
320 " for " +
this.wallet.Account +
". Error reported:\r\n\r\n" + ex.Message,
321 this.wallet.Account,
string.Empty,
"eDalerError", Tags);
325 if (!(this.@event is
null))
336 KeyValuePair<string, object>[] Tags =
new KeyValuePair<string, object>[]
338 new KeyValuePair<string, object>(
"Amount", this.amount),
339 new KeyValuePair<string, object>(
"Currency", this.
Uri.
Currency),
340 new KeyValuePair<string, object>(
"RefId", this.
Uri.
Id.ToString()),
341 new KeyValuePair<string, object>(
"Sender", this.
Uri.
State.Sender.Value),
344 new KeyValuePair<string, object>(
"Uri", this.
Uri.
UriString)
347 Append(ref Tags, this.quote);
349 Log.
Error(
"Unable to rollback wallet event of reservation of " + this.amount.ToString() +
350 " for " +
this.wallet.Account +
". Error reported:\r\n\r\n" + ex.Message,
351 this.wallet.Account,
string.Empty,
"eDalerError", Tags);
355 if (!await base.DoRollback())
Contains a pair of currencies, for currency conversion.
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 void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
CaseInsensitiveString Subdomain
Subdomain name.
XmppServer Server
XMPP Server.
Contains information about one XMPP address.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
Task< bool > SendMessage(string Type, string Id, string From, string To, string Language, string ContentXml)
Sends a Message stanza to a recipient.
CaseInsensitiveString Domain
Domain name.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
int IndexOf(CaseInsensitiveString value, StringComparison comparisonType)
Reports the zero-based index of the first occurrence of the specified string in the current System....
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 async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Static class that dynamically manages types and interfaces available in the runtime environment.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
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...
LegalComponent Legal
Legal component
Abstract base class for primary transaction objects (i.e. objects that control the transaction).
async Task< Wallet > GetWallet(XmppAddress For, EntityType ForType)
Gets the wallet of an entity in an eDaler transaction.
Handles the local reservation of eDaler.
override async Task< bool > DoCommit()
Performs actual commit.
override void LogEvent(string To, string From, decimal Amount, string Currency, KeyValuePair< string, object >[] Tags)
Logs an event corresponding to the transaction.
override async Task< bool > DoPrepare()
Performs actual preparation.
LocalReservation(EDalerUri Uri, bool ValidateSenderSignature)
Handles the local reservation of eDaler.
override async Task< bool > DoExecute()
Performs actual execution.
override async Task< bool > DoRollback()
Performs actual rollback.
Abstract base class for eDaler URIs
string UriString
Original URI String.
EntityType FromType
Type of sender
EDalerUriState State
URI State object.
EDalerComponent EDaler
eDaler component reference
byte[] PreSign
Binary representation of URI, before appending signature.
byte[] Signature
Digital signature.
DateTime Created
When URI was created
decimal TotalAmount
Total amount: Amount+AmountExtra
byte[] EncryptedMessage
Encrypted message for recipient. If EncryptionPublicKey is null, the message is just UTF-8 encoded.
Retains the current balance of an account.
Provisioning and registry service component.
Interface for currency conversion quotes.
string Source
Source of quote.
DateTime Timestamp
Timestamp of quote.
CaseInsensitiveString FromCurrency
Conversion from this currency.
decimal Rate
Exchange rate.
CaseInsensitiveString ToCurrency
Conversion to this currency.
Interface for currency converter services
Task< ICurrencyConverterQuote > GetCurrencyConversionQuote(CaseInsensitiveString FromCurrency, CaseInsensitiveString ToCurrency)
Gets a Currency Exchange Rate from one currency to another.
EntityType
Type of entity referred to in transaction.