import 'dart:developer'; import 'package:dartz/dartz.dart'; import 'package:data_channel/data_channel.dart'; import 'package:injectable/injectable.dart'; import '../../../domain/wallet/wallet.dart'; import '../datasources/wallet_remote_data_provider.dart'; @Injectable(as: IWalletRepository) class WalletRepository implements IWalletRepository { final WalletRemoteDataProvider _remoteDataProvider; final String _logName = 'WalletRepository'; WalletRepository(this._remoteDataProvider); @override Future> getWallet() => _run( 'getWallet', _remoteDataProvider.fetchWallet, (dto) => dto.toDomain(), ); @override Future> getTransactions({ required int page, int limit = 20, WalletCurrency? currency, List types = const [], DateTime? from, DateTime? to, }) => _run( 'getTransactions', () => _remoteDataProvider.fetchTransactions( page: page, limit: limit, currency: currency, types: types, from: from, to: to, ), (dto) => dto.toDomain(), ); @override Future> getExpiring() => _run( 'getExpiring', _remoteDataProvider.fetchExpiring, (dto) => dto.toDomain(), ); @override Future> previewExchange({ required int coins, }) => _run( 'previewExchange', () => _remoteDataProvider.previewExchange(coins: coins), (dto) => dto.toDomain(), ); @override Future> exchange({ required int coins, required String pin, required String idempotencyKey, }) => _run( 'exchange', () => _remoteDataProvider.exchange( coins: coins, pin: pin, idempotencyKey: idempotencyKey, ), (dto) => dto.toDomain(), ); @override Future> checkRecipient({ required String phone, }) => _run( 'checkRecipient', () => _remoteDataProvider.checkRecipient(phone: phone), (dto) => dto.toDomain(), ); @override Future> transfer({ required WalletCurrency currency, required int amount, required String recipientPhone, required String pin, required String idempotencyKey, }) => _run( 'transfer', () => _remoteDataProvider.transfer( currency: currency, amount: amount, recipientPhone: recipientPhone, pin: pin, idempotencyKey: idempotencyKey, ), (dto) => dto.toDomain(), ); Future> _run( String name, Future> Function() call, R Function(D dto) toDomain, ) async { try { final result = await call(); if (result.hasError) return left(result.error!); return right(toDomain(result.data as D)); } catch (e, s) { log(name, name: _logName, error: e, stackTrace: s); return left(const WalletFailure.unexpectedError()); } } }