mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
various eth+token tweaks
This commit is contained in:
parent
e6317a8507
commit
9711b79da5
7 changed files with 171 additions and 62 deletions
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue