various eth+token tweaks

This commit is contained in:
julian 2024-01-11 11:19:23 -06:00
parent e6317a8507
commit 9711b79da5
7 changed files with 171 additions and 62 deletions

View file

@ -107,6 +107,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
}
if (mounted) {
unawaited(ref.read(pCurrentTokenWallet)!.refresh());
await Navigator.of(context).pushNamed(
isDesktop ? DesktopTokenView.routeName : TokenView.routeName,
arguments: widget.walletId,

View file

@ -85,6 +85,9 @@ class _TransactionsListState extends ConsumerState<TokenTransactionsList> {
.walletIdEqualTo(widget.walletId)
.filter()
.subTypeEqualTo(TransactionSubType.ethToken)
.and()
.contractAddressEqualTo(
ref.read(pCurrentTokenWallet)!.tokenContract.address)
.sortByTimestampDesc();
_subscription = _query.watch().listen((event) {

View file

@ -150,6 +150,9 @@ class _WDesktopWalletSummaryState extends ConsumerState<DesktopWalletSummary> {
WalletRefreshButton(
walletId: walletId,
initialSyncStatus: widget.initialSyncStatus,
tokenContractAddress: widget.isToken
? ref.watch(pCurrentTokenWallet)!.tokenContract.address
: null,
),
if (coin == Coin.firo || coin == Coin.firoTestNet)
const SizedBox(

View file

@ -344,18 +344,12 @@ class WalletInfo implements IsarId {
required Set<String> newContractAddresses,
required Isar isar,
}) async {
// only update if there were changes to the name
if (tokenContractAddresses
.toSet()
.difference(newContractAddresses)
.isNotEmpty) {
await updateOtherData(
newEntries: {
WalletInfoKeys.tokenContractAddresses: newContractAddresses.toList(),
},
isar: isar,
);
}
await updateOtherData(
newEntries: {
WalletInfoKeys.tokenContractAddresses: newContractAddresses.toList(),
},
isar: isar,
);
}
//============================================================================

View file

@ -1,6 +1,7 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
import 'package:stackwallet/wallets/isar/providers/util/watcher.dart';
@ -8,13 +9,30 @@ import 'package:stackwallet/wallets/isar/providers/util/watcher.dart';
final _twiProvider = ChangeNotifierProvider.family<Watcher,
({String walletId, String contractAddress})>(
(ref, data) {
final collection = ref.watch(mainDBProvider).isar.tokenWalletInfo;
final isar = ref.watch(mainDBProvider).isar;
final collection = isar.tokenWalletInfo;
TokenWalletInfo? initial = collection
.where()
.walletIdTokenAddressEqualTo(data.walletId, data.contractAddress)
.findFirstSync();
if (initial == null) {
initial = TokenWalletInfo(
walletId: data.walletId,
tokenAddress: data.contractAddress,
tokenFractionDigits: isar.ethContracts
.getByAddressSync(data.contractAddress)
?.decimals ??
2,
);
isar.writeTxnSync(() => isar.tokenWalletInfo.putSync(initial!));
}
final watcher = Watcher(
collection
.where()
.walletIdTokenAddressEqualTo(data.walletId, data.contractAddress)
.findFirstSync()!,
initial,
collection: collection,
);
@ -27,7 +45,8 @@ final _twiProvider = ChangeNotifierProvider.family<Watcher,
final pTokenWalletInfo = Provider.family<TokenWalletInfo,
({String walletId, String contractAddress})>(
(ref, data) {
return ref.watch(_twiProvider(data)).value as TokenWalletInfo;
return ref.watch(_twiProvider(data).select((value) => value.value))
as TokenWalletInfo;
},
);

View file

@ -17,6 +17,7 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/eth_commons.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
@ -364,30 +365,124 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface {
}
@override
Future<TxData> confirmSend({required TxData txData}) {
// TODO: implement confirmSend
throw UnimplementedError();
Future<TxData> prepareSend({required TxData txData}) async {
final int
rate; // TODO: use BigInt for feeObject whenever FeeObject gets redone
final feeObject = await fees;
switch (txData.feeRateType!) {
case FeeRateType.fast:
rate = feeObject.fast;
break;
case FeeRateType.average:
rate = feeObject.medium;
break;
case FeeRateType.slow:
rate = feeObject.slow;
break;
case FeeRateType.custom:
throw UnimplementedError("custom eth fees");
}
final feeEstimate = await estimateFeeFor(Amount.zero, rate);
// bool isSendAll = false;
// final availableBalance = balance.spendable;
// if (satoshiAmount == availableBalance) {
// isSendAll = true;
// }
//
// if (isSendAll) {
// //Subtract fee amount from send amount
// satoshiAmount -= feeEstimate;
// }
final client = getEthClient();
final myAddress = (await getCurrentReceivingAddress())!.value;
final myWeb3Address = web3.EthereumAddress.fromHex(myAddress);
final amount = txData.recipients!.first.amount;
final address = txData.recipients!.first.address;
// final est = await client.estimateGas(
// sender: myWeb3Address,
// to: web3.EthereumAddress.fromHex(address),
// gasPrice: web3.EtherAmount.fromUnitAndValue(
// web3.EtherUnit.wei,
// rate,
// ),
// amountOfGas: BigInt.from((cryptoCurrency as Ethereum).gasLimit),
// value: web3.EtherAmount.inWei(amount.raw),
// );
final nonce = txData.nonce ??
await client.getTransactionCount(myWeb3Address,
atBlock: const web3.BlockNum.pending());
// final nResponse = await EthereumAPI.getAddressNonce(address: myAddress);
// print("==============================================================");
// print("ETH client.estimateGas: $est");
// print("ETH estimateFeeFor : $feeEstimate");
// print("ETH nonce custom response: $nResponse");
// print("ETH actual nonce : $nonce");
// print("==============================================================");
final tx = web3.Transaction(
to: web3.EthereumAddress.fromHex(address),
gasPrice: web3.EtherAmount.fromUnitAndValue(
web3.EtherUnit.wei,
rate,
),
maxGas: (cryptoCurrency as Ethereum).gasLimit,
value: web3.EtherAmount.inWei(amount.raw),
nonce: nonce,
);
return txData.copyWith(
nonce: tx.nonce,
web3dartTransaction: tx,
fee: feeEstimate,
feeInWei: BigInt.from(rate),
chainId: (await client.getChainId()),
);
}
@override
Future<TxData> prepareSend({required TxData txData}) {
// TODO: implement prepareSend
throw UnimplementedError();
Future<TxData> confirmSend({required TxData txData}) async {
final client = getEthClient();
final txid = await client.sendTransaction(
_credentials,
txData.web3dartTransaction!,
chainId: txData.chainId!.toInt(),
);
return txData.copyWith(
txid: txid,
txHash: txid,
);
}
@override
Future<void> recover({required bool isRescan}) async {
if (isRescan) {
await mainDB.deleteWalletBlockchainData(walletId);
await _generateAndSaveAddress(
await getMnemonic(),
await getMnemonicPassphrase(),
);
await updateBalance();
await updateTransactions(isRescan: true);
} else {
//
}
await refreshMutex.protect(() async {
if (isRescan) {
await mainDB.deleteWalletBlockchainData(walletId);
await _generateAndSaveAddress(
await getMnemonic(),
await getMnemonicPassphrase(),
);
await updateBalance();
await updateTransactions(isRescan: true);
} else {
await _generateAndSaveAddress(
await getMnemonic(),
await getMnemonicPassphrase(),
);
unawaited(updateBalance());
unawaited(updateTransactions());
}
});
}
@override

View file

@ -283,9 +283,15 @@ class EthTokenWallet extends Wallet {
}
@override
Future<void> recover({required bool isRescan}) {
// TODO: implement recover
throw UnimplementedError();
Future<void> recover({required bool isRescan}) async {
try {
throw Exception();
} catch (_, s) {
Logging.instance.log(
"Eth token wallet recover called. This should not happen. Stacktrace: $s",
level: LogLevel.Warning,
);
}
}
@override
@ -401,30 +407,29 @@ class EthTokenWallet extends Wallet {
for (final tuple in data) {
// ignore all non Transfer events (for now)
if (tuple.tx.topics[0] == kTransferEventSignature) {
final Amount amount;
final Amount txFee = tuple.extra.gasUsed * tuple.extra.gasPrice;
String fromAddress, toAddress;
amount = Amount(
final amount = Amount(
rawValue: tuple.tx.data.toBigIntFromHex,
fractionDigits: tokenContract.decimals,
);
fromAddress = _addressFromTopic(
final addressFrom = _addressFromTopic(
tuple.tx.topics[1],
);
toAddress = _addressFromTopic(
final addressTo = _addressFromTopic(
tuple.tx.topics[2],
);
bool isIncoming;
bool isSentToSelf = false;
if (fromAddress == addressString) {
isIncoming = false;
if (toAddress == addressString) {
isSentToSelf = true;
final TransactionType txType;
if (addressTo == addressString) {
if (addressFrom == addressTo) {
txType = TransactionType.sentToSelf;
} else {
txType = TransactionType.incoming;
}
} else if (toAddress == addressString) {
isIncoming = true;
} else if (addressFrom == addressString) {
txType = TransactionType.outgoing;
} else {
// ignore for now I guess since anything here is not reflected in
// balance anyways
@ -435,17 +440,6 @@ class EthTokenWallet extends Wallet {
// "${tuple.item1.toString()}");
}
final TransactionType txType;
if (isIncoming) {
if (fromAddress == toAddress) {
txType = TransactionType.sentToSelf;
} else {
txType = TransactionType.incoming;
}
} else {
txType = TransactionType.outgoing;
}
final otherData = {
"nonce": tuple.extra.nonce,
"isCancelled": false,