Files
sxchnge/frontend/packages/sxchnge_kyc/lib/src/services/dummy.dart
T

98 lines
2.9 KiB
Dart

import '../models/identity.dart';
import '../models/limits.dart';
import '../transport/contracts.dart';
import 'contracts.dart';
/// Process-local backend stand-in. It never stores or sends document bytes.
class DummyIdentityService implements IdentityService {
DummyIdentityService({this.delay = const Duration(milliseconds: 450)});
final Duration delay;
IdentityDTO _record = const IdentityDTO('unverified');
String? _lastKey;
KycError? nextError;
@override
bool get isSimulated => true;
Future<void> _wait() async {
await Future<void>.delayed(delay);
final error = nextError;
nextError = null;
if (error != null) throw KycException(error);
}
@override
Future<Identity> fetch() async {
await _wait();
return IdentityMapper.fromDTO(_record);
}
@override
Future<Identity> submit({
required Photo passport,
required Photo selfie,
required String idempotencyKey,
}) async {
await _wait();
if (_lastKey == idempotencyKey) return IdentityMapper.fromDTO(_record);
if (!IdentityMapper.fromDTO(_record).canSubmit)
throw const KycException(KycError.conflict);
if (passport.bytes.isEmpty || selfie.bytes.isEmpty)
throw const KycException(KycError.incomplete);
_lastKey = idempotencyKey;
_record = IdentityDTO('pending', id: idempotencyKey);
return IdentityMapper.fromDTO(_record);
}
/// Explicit demo-only human decision stand-in; unavailable in real adapters.
void review(IdentityStatus status, {ReviewReason? reason}) {
if (_record.status != 'pending')
throw const KycException(KycError.conflict);
if (![
IdentityStatus.approved,
IdentityStatus.changesRequested,
IdentityStatus.denied,
].contains(status))
throw const KycException(KycError.conflict);
_record = IdentityDTO(status.name, id: _record.id, reason: reason?.name);
}
}
/// Mimics backend policy evaluation. Widgets/providers never compute active caps.
/// Values are illustrative fixtures, not the product's real limits policy.
class DummyLimitsService implements LimitsService {
DummyLimitsService(this.identity);
final IdentityService identity;
@override
Future<Limits> fetch() async {
final record = await identity.fetch();
final approved = record.status == IdentityStatus.approved;
return LimitsMapper.fromDTO(
LimitsDTO(
tier: approved ? 'verified' : 'basic',
simulated: true,
rows: [
LimitDTO(
'day',
'EUR',
10000,
250000,
approved ? 250000 : 10000,
(approved ? 250000 : 10000) - 4000,
3000,
1000,
),
LimitDTO(
'month',
'EUR',
50000,
1000000,
approved ? 1000000 : 50000,
(approved ? 1000000 : 50000) - 19000,
18000,
1000,
),
],
),
);
}
}