Build exchange workspace and shared transaction services (#28)
This commit is contained in:
1 parent
52b7135eda
commit
c496da8a55
48 files changed
+4757
-120
No files matched your search
@@ -0,0 +1,113 @@
|
||||
enum TransferKind { topUp, exchange, payout }
|
||||
|
||||
enum OperationStatus { pending, completed, failed }
|
||||
|
||||
enum WalletError {
|
||||
unavailable,
|
||||
invalidAmount,
|
||||
insufficientFunds,
|
||||
limitExceeded,
|
||||
expiredQuote,
|
||||
invalidRecipient,
|
||||
unsupported,
|
||||
notFound,
|
||||
uncertain,
|
||||
}
|
||||
|
||||
class WalletException implements Exception {
|
||||
const WalletException(this.code);
|
||||
final WalletError code;
|
||||
}
|
||||
|
||||
class CurrencyAccount {
|
||||
const CurrencyAccount({
|
||||
required this.id,
|
||||
required this.currency,
|
||||
required this.precision,
|
||||
required this.available,
|
||||
});
|
||||
final String id, currency;
|
||||
final int precision, available;
|
||||
|
||||
/// Locale-aware decimal input, integer money. Grouping/exponents are rejected.
|
||||
int? parse(String input) {
|
||||
final value = input.trim().replaceAll(',', '.');
|
||||
if (!RegExp(r'^\d+(\.\d+)?$').hasMatch(value)) return null;
|
||||
final parts = value.split('.');
|
||||
if (parts.length > 1 && parts[1].length > precision) return null;
|
||||
final major = int.tryParse(parts[0]);
|
||||
if (major == null || major > 100000000) return null;
|
||||
final fraction = parts.length > 1
|
||||
? int.parse(parts[1].padRight(precision, '0'))
|
||||
: 0;
|
||||
return major * scale + fraction;
|
||||
}
|
||||
|
||||
int get scale {
|
||||
var v = 1;
|
||||
for (var i = 0; i < precision; i++) {
|
||||
v *= 10;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
class TransferRequest {
|
||||
const TransferRequest({
|
||||
required this.kind,
|
||||
required this.source,
|
||||
required this.amount,
|
||||
this.destination,
|
||||
this.recipient = '',
|
||||
});
|
||||
final TransferKind kind;
|
||||
final String source;
|
||||
final int amount;
|
||||
final String? destination;
|
||||
final String recipient;
|
||||
}
|
||||
|
||||
class Quote {
|
||||
const Quote({
|
||||
required this.id,
|
||||
required this.request,
|
||||
required this.fee,
|
||||
required this.debit,
|
||||
required this.credit,
|
||||
required this.expiresAt,
|
||||
required this.rateNumerator,
|
||||
required this.rateDenominator,
|
||||
});
|
||||
final String id;
|
||||
final TransferRequest request;
|
||||
final int fee, debit, credit, rateNumerator, rateDenominator;
|
||||
final DateTime expiresAt;
|
||||
}
|
||||
|
||||
class WalletOperation {
|
||||
const WalletOperation({
|
||||
required this.id,
|
||||
required this.quote,
|
||||
required this.status,
|
||||
required this.createdAt,
|
||||
});
|
||||
final String id;
|
||||
final Quote quote;
|
||||
final OperationStatus status;
|
||||
final DateTime createdAt;
|
||||
}
|
||||
|
||||
class WalletSnapshot {
|
||||
WalletSnapshot({
|
||||
required List<CurrencyAccount> accounts,
|
||||
required List<WalletOperation> operations,
|
||||
}) : accounts = List.unmodifiable(accounts),
|
||||
operations = List.unmodifiable(operations);
|
||||
final List<CurrencyAccount> accounts;
|
||||
final List<WalletOperation> operations;
|
||||
}
|
||||
|
||||
class AccountProfile {
|
||||
const AccountProfile(this.locale);
|
||||
final String locale;
|
||||
}
|
||||
Reference in new issue
Block a user