Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #73 from MXCzkEVM/main
Browse files Browse the repository at this point in the history
1.4.0
  • Loading branch information
sheenhx authored Sep 26, 2023
2 parents b430f57 + 1442165 commit 4a75ac0
Show file tree
Hide file tree
Showing 58 changed files with 979 additions and 294 deletions.
10 changes: 10 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>

<provider
android:name="com.pichillilorenzo.flutter_inappwebview.InAppWebViewFileProvider"
android:authorities="${applicationId}.flutter_inappwebview.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>

<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />
Expand Down
4 changes: 3 additions & 1 deletion assets/flutter_i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,5 +279,7 @@
"network_not_found": "Network not found",
"checking_balance": "Checking balance...",
"no_balance": "You have no balance",
"no_balance_tip": "You currently have no MXC in your wallet.\nYou can either receive tokens or choose to claim a username later."
"no_balance_tip": "You currently have no MXC in your wallet.\nYou can either receive tokens or choose to claim a username later.",
"signature_request": "Signature request",
"sign": "Sign"
}
2 changes: 1 addition & 1 deletion lib/common/components/balance_panel/balance.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export 'presentation/balance_panel.dart';
export 'presentation/balance_panel.dart';
2 changes: 1 addition & 1 deletion lib/common/components/components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export 'recent_transactions/recent_transactions.dart';
export 'gradient_text.dart';
export 'grey_container.dart';
export 'balance_panel/balance.dart';
export 'snack_bar.dart';
export 'snack_bar.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:datadashwallet/common/components/recent_transactions/entity/transaction_history_model.dart';
import 'package:mxc_logic/mxc_logic.dart';
import 'package:datadashwallet/core/core.dart';

class TransactionsHistoryRepository extends ControlledCacheRepository {
@override
final String zone = 'transaction-history';

late final Field<List<TransactionHistoryModel>> transactionsHistory =
fieldWithDefault<List<TransactionHistoryModel>>('items', [],
serializer: (b) => b
.map((e) => {
'chainId': e.chainId,
'txList': e.txList.map((e) => e.toMap()).toList()
})
.toList(),
deserializer: (b) => (b as List)
.map((e) => TransactionHistoryModel(
chainId: e['chainId'],
txList: (e['txList'] as List)
.map((e) => TransactionModel.fromMap(e))
.toList(),
))
.toList());

List<TransactionHistoryModel> get items => transactionsHistory.value;

void addItem(TransactionHistoryModel item) =>
transactionsHistory.value = [...transactionsHistory.value, item];

void addItemTx(TransactionModel item, int index) {
final newList = transactionsHistory.value;
newList[index].txList.insert(0, item);
transactionsHistory.value = newList;
}

void updateItem(TransactionHistoryModel item, int index) {
final newList = transactionsHistory.value;
newList.removeAt(index);
newList.insert(index, item);
transactionsHistory.value = newList;
}

void updateItemTx(TransactionModel item, int index, int txIndex) {
final newList = transactionsHistory.value;

newList[index].txList[txIndex] = item;

transactionsHistory.value = newList;
}

void removeItem(TransactionHistoryModel item) =>
transactionsHistory.value = transactionsHistory.value
.where((e) => e.chainId != item.chainId)
.toList();

void removeAll() => transactionsHistory.value = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import 'package:datadashwallet/common/common.dart';
import 'package:datadashwallet/core/core.dart';
import 'package:mxc_logic/mxc_logic.dart';
import '../entity/transaction_history_model.dart';
import 'transactions_repository.dart';
import 'package:web3dart/web3dart.dart';

class TransactionsHistoryUseCase extends ReactiveUseCase {
TransactionsHistoryUseCase(this._repository, this._web3Repository);

final Web3Repository _web3Repository;

final TransactionsHistoryRepository _repository;

late final ValueStream<List<TransactionHistoryModel>> transactionsHistory =
reactiveField(_repository.transactionsHistory);

List<TransactionHistoryModel> getTransactionsHistory() => _repository.items;

List<String> updatingTxList = [];

void addItem(TransactionHistoryModel item) {
_repository.addItem(item);
update(transactionsHistory, _repository.items);
}

void updateItem(TransactionHistoryModel item, int index) {
_repository.updateItem(item, index);
update(transactionsHistory, _repository.items);
}

void updateItemTx(TransactionModel item, int selectedNetworkChainId) {
final txHistory = transactionsHistory.value
.firstWhere((element) => element.chainId == selectedNetworkChainId);

final index = transactionsHistory.value.indexOf(txHistory);
final txIndex = txHistory.txList.indexWhere(
(element) => element.hash == item.hash,
);

if (txIndex == -1) {
_repository.addItemTx(item, index);
} else {
_repository.updateItemTx(item, index, txIndex);
}

update(transactionsHistory, _repository.items);
}

void removeAll() {
_repository.removeAll();
update(transactionsHistory, _repository.items);
}

void removeItem(TransactionHistoryModel item) {
_repository.removeItem(item);
update(transactionsHistory, _repository.items);
}

void spyOnTransaction(TransactionModel item, int chainId) {
if (!updatingTxList.contains(item.hash)) {
updatingTxList.add(item.hash);
final stream = _web3Repository.tokenContract.spyTransaction(item.hash);
stream.onData((succeeded) {
if (succeeded) {
final updatedItem = item.copyWith(status: TransactionStatus.done);
updateItemTx(updatedItem, chainId);
updatingTxList.remove(item.hash);
stream.cancel();
}
});
}
}

void checkForPendingTransactions(int chainId) {
if (!Config.isMxcChains(chainId)) {
final index = transactionsHistory.value
.indexWhere((element) => element.chainId == chainId);

if (index != -1) {
final chainTx = transactionsHistory.value[index];
final pendingTxList = chainTx.txList
.where((element) => element.status == TransactionStatus.pending);
for (TransactionModel pendingTx in pendingTxList) {
spyOnTransaction(pendingTx, chainId);
}
}
}
}

void spyOnUnknownTransaction(
String hash, String address, Token token, int chainId) async {
TransactionInformation? receipt;

receipt = await _web3Repository.tokenContract
.getTransactionByHashCustomChain(hash);

if (receipt != null) {
final tx = TransactionModel.fromTransaction(receipt, address, token);
spyOnTransaction(tx, chainId);
updateItemTx(tx, chainId);
}
}

void checkChainAvailability(int chainId) {
final index = transactionsHistory.value
.indexWhere((element) => element.chainId == chainId);

if (index == -1) {
addItem(TransactionHistoryModel(chainId: chainId, txList: []));
return;
}
update(transactionsHistory, _repository.items);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:mxc_logic/mxc_logic.dart';

class TransactionHistoryModel {
TransactionHistoryModel({
required this.chainId,
required this.txList,
});

int chainId;
List<TransactionModel> txList;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import 'package:datadashwallet/common/common.dart';
import 'package:datadashwallet/core/core.dart';
import 'package:datadashwallet/features/dapps/dapps.dart';
import 'package:datadashwallet/features/wallet/wallet.dart';
import 'package:mxc_logic/mxc_logic.dart';
import './utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:mxc_ui/mxc_ui.dart';

enum TransactionType { sent, received, all }

enum TransactionStatus { done, pending, failed }
export 'domain/transactions_use_case.dart';
export 'domain/transactions_repository.dart';
export 'entity/transaction_history_model.dart';

class RecentTransactions extends HookConsumerWidget {
const RecentTransactions({
Expand All @@ -22,12 +23,13 @@ class RecentTransactions extends HookConsumerWidget {
});

final String? walletAddress;
final List<WannseeTransactionModel>? transactions;
final List<TransactionModel>? transactions;
final List<Token> tokens;
final NetworkType? networkType;

@override
Widget build(BuildContext context, WidgetRef ref) {
final presenter = ref.read(walletContainer.actions);
return transactions != null && transactions!.isEmpty
? Center(
child: Text(
Expand Down Expand Up @@ -67,9 +69,7 @@ class RecentTransactions extends HookConsumerWidget {
route.featureDialog(
maintainState: false,
OpenAppPage(
url: RecentTransactionsUtils
.getViewOtherTransactionsLink(
networkType!, walletAddress!),
url: presenter.getViewOtherTransactionsLink(),
),
),
),
Expand Down
120 changes: 21 additions & 99 deletions lib/common/components/recent_transactions/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,106 +75,28 @@ class RecentTransactionsUtils {
}

static List<RecentTrxListItem> generateTx(String walletAddressHash,
List<WannseeTransactionModel> items, List<Token> tokensList) {
List<RecentTrxListItem> widgets = [];

for (int i = 0; i < items.length; i++) {
final currentTx = items[i];
String amount = '0';
String symbol = 'Unknown';
String timeStamp = 'Unknown';
String hash = currentTx.hash ?? 'Unknown';
TransactionType transactionType = TransactionType.sent;
TransactionStatus transactionStatus = TransactionStatus.done;
String logoUrl = 'assets/svg/networks/unknown.svg';

// two type of tx : coin_transfer from filtered tx list & token transfer from token transfer list
// If not 'contract_call' or 'coin_transfer' then empty and that means failed in other words
// another tx that we have are : pending coin transfer (which is received on both sides) &
// pending token transfer (which is only received on the sender side)
if (currentTx.result == 'pending') {
// could be contract_call || coin_transfer
transactionStatus = TransactionStatus.pending;
final time = DateTime.now();
timeStamp = Formatter.localTime(time);

transactionType = RecentTransactionsUtils.checkForTransactionType(
walletAddressHash, currentTx.from!.hash!.toLowerCase());
amount = Formatter.convertWeiToEth(
currentTx.value ?? '0', Config.ethDecimals);
logoUrl = Config.mxcLogoUri;
symbol = Config.mxcName;

if (currentTx.decodedInput != null) {
if (currentTx.to?.hash != null) {
final tokenIndex = tokensList
.indexWhere((element) => element.address == currentTx.to!.hash);
if (tokenIndex != -1) {
logoUrl = tokensList[tokenIndex].logoUri!;
}
symbol = currentTx.to!.name!;
amount = Formatter.convertWeiToEth(
currentTx.decodedInput?.parameters?[1].value ?? '0',
Config.ethDecimals);
}
}
} else if (currentTx.txTypes != null &&
currentTx.txTypes!.contains('coin_transfer')) {
logoUrl = Config.mxcLogoUri;
symbol = Config.mxcSymbol;
timeStamp = Formatter.localTime(currentTx.timestamp!);

transactionType = RecentTransactionsUtils.checkForTransactionType(
walletAddressHash, currentTx.from!.hash!.toLowerCase());
amount = Formatter.convertWeiToEth(
currentTx.value ?? '0', Config.ethDecimals);
} else if (currentTx.txTypes == null &&
currentTx.tokenTransfers != null &&
currentTx.tokenTransfers![0].type == 'token_transfer') {
symbol = currentTx.tokenTransfers![0].token!.name!;

if (currentTx.tokenTransfers![0].token!.name != null) {
final tokenIndex = tokensList.indexWhere((element) =>
element.address == currentTx.tokenTransfers![0].token!.address!);
if (tokenIndex != -1) {
logoUrl = tokensList[tokenIndex].logoUri!;
}
}

timeStamp =
Formatter.localTime(currentTx.tokenTransfers![0].timestamp!);

amount = Formatter.convertWeiToEth(
currentTx.tokenTransfers![0].total!.value ?? '0',
Config.ethDecimals);
hash = currentTx.tokenTransfers![0].txHash ?? "Unknown";
transactionType = RecentTransactionsUtils.checkForTransactionType(
walletAddressHash,
currentTx.tokenTransfers![0].from!.hash!.toLowerCase(),
);
}

widgets.add(RecentTrxListItem(
List<TransactionModel> items, List<Token> tokensList) {
return items.map((e) {
final foundToken = tokensList.firstWhere(
(element) => element.address == e.token.address,
orElse: () => Token());
final logoUrl = foundToken.logoUri ??
e.token.logoUri ??
'assets/svg/networks/unknown.svg';
final decimal =
foundToken.decimals ?? e.token.decimals ?? Config.ethDecimals;
final symbol = foundToken.symbol ?? e.token.symbol ?? 'Unknown';

return RecentTrxListItem(
logoUrl: logoUrl,
amount: amount,
amount: Formatter.convertWeiToEth(e.value, decimal),
symbol: symbol,
timestamp: timeStamp,
txHash: hash,
transactionType: transactionType,
transactionStatus: transactionStatus,
));
}
return widgets;
}

static String getViewOtherTransactionsLink(
NetworkType networkType, String walletAddress) {
String baseUrl = 'explorer.mxc.com';

if (networkType == NetworkType.testnet) {
baseUrl = 'wannsee-explorer.mxc.com';
}

return 'https://$baseUrl/address/$walletAddress';
timestamp:
e.timeStamp == null ? "Unknown" : Formatter.localTime(e.timeStamp!),
txHash: e.hash,
transactionType: e.type,
transactionStatus: e.status,
);
}).toList();
}
}
Loading

0 comments on commit 4a75ac0

Please sign in to comment.