Add saved payout destination UX and service contracts (#54)
This commit is contained in:
1 parent
a5689876ff
commit
24af794112
49 files changed
+4687
-62
No files matched your search
@@ -6,6 +6,7 @@ import 'package:sxchnge_analytics/sxchnge_analytics.dart';
|
||||
|
||||
import 'package:sxchnge_auth/sxchnge_auth.dart';
|
||||
|
||||
import '../destinations/models.dart';
|
||||
import '../models/wallet.dart';
|
||||
import 'wallet.dart';
|
||||
|
||||
@@ -40,16 +41,18 @@ class TransferProvider extends ChangeNotifier {
|
||||
if (!accounts.any((a) => a.id == destination) || destination == source) {
|
||||
destination = accounts.where((a) => a.id != source).firstOrNull?.id;
|
||||
}
|
||||
if (!wallet.service.isSimulated && kind == TransferKind.payout) {
|
||||
recipient = wallet.account(source)?.payoutMethod ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
void _walletChanged() {
|
||||
if (_disposed) return;
|
||||
final previous = source;
|
||||
_syncAccounts();
|
||||
if (source != previous) notifyListeners();
|
||||
if (source != previous) {
|
||||
payoutDestination = null;
|
||||
payoutLabel = '';
|
||||
recipient = '';
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
final WalletProvider wallet;
|
||||
@@ -58,6 +61,8 @@ class TransferProvider extends ChangeNotifier {
|
||||
String source;
|
||||
String? destination;
|
||||
String amount = '', recipient = '';
|
||||
DestinationInput? payoutDestination;
|
||||
String payoutLabel = '';
|
||||
Quote? quote;
|
||||
WalletOperation? result;
|
||||
WalletError? error;
|
||||
@@ -72,7 +77,7 @@ class TransferProvider extends ChangeNotifier {
|
||||
TransferKind.payout => JourneyKind.payout,
|
||||
};
|
||||
bool get hasDraft =>
|
||||
amount.isNotEmpty || (wallet.service.isSimulated && recipient.isNotEmpty);
|
||||
amount.isNotEmpty || payoutDestination != null || recipient.isNotEmpty;
|
||||
bool get expired =>
|
||||
quote != null && !DateTime.now().isBefore(quote!.expiresAt);
|
||||
void change({
|
||||
@@ -80,8 +85,17 @@ class TransferProvider extends ChangeNotifier {
|
||||
String? destination,
|
||||
String? amount,
|
||||
String? recipient,
|
||||
DestinationInput? payoutDestination,
|
||||
String? payoutLabel,
|
||||
}) {
|
||||
if (busy || uncertain) return;
|
||||
if (source != null && source != this.source) {
|
||||
this.payoutDestination = null;
|
||||
this.payoutLabel = '';
|
||||
recipient = '';
|
||||
}
|
||||
this.payoutDestination = payoutDestination ?? this.payoutDestination;
|
||||
this.payoutLabel = payoutLabel ?? this.payoutLabel;
|
||||
this.source = source ?? this.source;
|
||||
this.destination = destination ?? this.destination;
|
||||
this.amount = amount ?? this.amount;
|
||||
@@ -96,6 +110,36 @@ class TransferProvider extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> selectPayout(DestinationInput input) async {
|
||||
if (busy || uncertain || wallet.destinations == null) return;
|
||||
busy = true;
|
||||
error = null;
|
||||
notifyListeners();
|
||||
try {
|
||||
final service = wallet.destinations!;
|
||||
final assessment = await service.assess(
|
||||
input,
|
||||
PayoutContext(source, amount: wallet.account(source)?.parse(amount)),
|
||||
);
|
||||
if (!assessment.eligible)
|
||||
throw const DestinationException(DestinationIssue.unsupported);
|
||||
final details = input is OneTimeDestination
|
||||
? input.details
|
||||
: (await service.get((input as SavedReference).id)).details;
|
||||
if (_disposed) return;
|
||||
busy = false;
|
||||
change(payoutDestination: input, payoutLabel: details.display);
|
||||
} catch (_) {
|
||||
if (_disposed) return;
|
||||
payoutDestination = null;
|
||||
payoutLabel = '';
|
||||
error = WalletError.destinationChanged;
|
||||
}
|
||||
if (_disposed) return;
|
||||
busy = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void edit() {
|
||||
if (!busy && !uncertain) {
|
||||
quote = null;
|
||||
@@ -133,6 +177,7 @@ class TransferProvider extends ChangeNotifier {
|
||||
amount: money,
|
||||
destination: kind == TransferKind.exchange ? destination : null,
|
||||
recipient: recipient.trim(),
|
||||
payoutDestination: payoutDestination,
|
||||
),
|
||||
);
|
||||
if (_disposed || revision != _revision) return;
|
||||
@@ -142,6 +187,10 @@ class TransferProvider extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
if (_disposed) return;
|
||||
error = _code(e);
|
||||
if (error == WalletError.destinationChanged) {
|
||||
payoutDestination = null;
|
||||
payoutLabel = '';
|
||||
}
|
||||
recorder.finish(op, failure: _failure(error!));
|
||||
}
|
||||
if (_disposed) return;
|
||||
@@ -225,6 +274,11 @@ class TransferProvider extends ChangeNotifier {
|
||||
uncertain = false;
|
||||
} else {
|
||||
error = _code(e);
|
||||
if (error == WalletError.destinationChanged) {
|
||||
quote = null;
|
||||
payoutDestination = null;
|
||||
payoutLabel = '';
|
||||
}
|
||||
}
|
||||
// All transport/unexpected failures are ambiguous after execution started.
|
||||
uncertain = [
|
||||
@@ -247,6 +301,7 @@ class TransferProvider extends ChangeNotifier {
|
||||
error = null;
|
||||
factorError = null;
|
||||
recipient = '';
|
||||
payoutDestination = null;
|
||||
recorder.finish(op, simulated: wallet.service.isSimulated);
|
||||
wallet.track(value, recorder, journey);
|
||||
_handedOff = true;
|
||||
|
||||
Reference in new issue
Block a user