untested stellar tor listener

This commit is contained in:
julian 2024-05-03 18:04:57 -06:00
parent 65941478b8
commit dd45c870f6

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:mutex/mutex.dart';
import 'package:socks5_proxy/socks.dart'; import 'package:socks5_proxy/socks.dart';
import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
@ -11,6 +12,9 @@ import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart'
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/tor_service.dart';
import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
@ -23,11 +27,47 @@ import 'package:stackwallet/wallets/wallet/intermediate/bip39_wallet.dart';
import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart' as stellar; import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart' as stellar;
class StellarWallet extends Bip39Wallet<Stellar> { class StellarWallet extends Bip39Wallet<Stellar> {
StellarWallet(CryptoCurrencyNetwork network) : super(Stellar(network)); StellarWallet(CryptoCurrencyNetwork network) : super(Stellar(network)) {
final bus = GlobalEventBus.instance;
stellar.StellarSDK get stellarSdk { // Listen for tor status changes.
if (_stellarSdk == null) { _torStatusListener = bus.on<TorConnectionStatusChangedEvent>().listen(
_updateSdk(); (event) async {
switch (event.newStatus) {
case TorConnectionStatus.connecting:
if (!_torConnectingLock.isLocked) {
await _torConnectingLock.acquire();
}
_requireMutex = true;
break;
case TorConnectionStatus.connected:
case TorConnectionStatus.disconnected:
if (_torConnectingLock.isLocked) {
_torConnectingLock.release();
}
_requireMutex = false;
break;
}
},
);
// Listen for tor preference changes.
_torPreferenceListener = bus.on<TorPreferenceChangedEvent>().listen(
(event) async {
_stellarSdk?.httpClient.close();
_stellarSdk = null;
},
);
}
Future<stellar.StellarSDK> get stellarSdk async {
if (_requireMutex) {
await _torConnectingLock.protect(() async {
_stellarSdk ??= _getFreshSdk();
});
} else {
_stellarSdk ??= _getFreshSdk();
} }
return _stellarSdk!; return _stellarSdk!;
} }
@ -44,19 +84,32 @@ class StellarWallet extends Bip39Wallet<Stellar> {
} }
// ============== Private ==================================================== // ============== Private ====================================================
// add finalizer to cancel stream subscription when all references to an
// instance of this becomes inaccessible
final _ = Finalizer<StellarWallet>(
(p0) {
p0._torPreferenceListener?.cancel();
p0._torStatusListener?.cancel();
},
);
StreamSubscription<TorConnectionStatusChangedEvent>? _torStatusListener;
StreamSubscription<TorPreferenceChangedEvent>? _torPreferenceListener;
final Mutex _torConnectingLock = Mutex();
bool _requireMutex = false;
stellar.StellarSDK? _stellarSdk; stellar.StellarSDK? _stellarSdk;
Future<int> _getBaseFee() async { Future<int> _getBaseFee() async {
final fees = await stellarSdk.feeStats.execute(); final fees = await (await stellarSdk).feeStats.execute();
return int.parse(fees.lastLedgerBaseFee); return int.parse(fees.lastLedgerBaseFee);
} }
void _updateSdk() { stellar.StellarSDK _getFreshSdk() {
final currentNode = getCurrentNode(); final currentNode = getCurrentNode();
HttpClient? _httpClient; HttpClient? _httpClient;
// TODO [prio=med]: refactor out and call before requests in case Tor is enabled/disabled, listen to prefs change, or similar.
if (prefs.useTor) { if (prefs.useTor) {
final ({InternetAddress host, int port}) proxyInfo = final ({InternetAddress host, int port}) proxyInfo =
TorService.sharedInstance.getProxyInfo(); TorService.sharedInstance.getProxyInfo();
@ -73,8 +126,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
); );
} }
_stellarSdk?.httpClient.close(); return stellar.StellarSDK(
_stellarSdk = stellar.StellarSDK(
"${currentNode.host}:${currentNode.port}", "${currentNode.host}:${currentNode.port}",
httpClient: _httpClient, httpClient: _httpClient,
); );
@ -84,7 +136,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
bool exists = false; bool exists = false;
try { try {
final receiverAccount = await stellarSdk.accounts.account(accountId); final receiverAccount =
await (await stellarSdk).accounts.account(accountId);
if (receiverAccount.accountId != "") { if (receiverAccount.accountId != "") {
exists = true; exists = true;
} }
@ -191,7 +244,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
@override @override
Future<TxData> confirmSend({required TxData txData}) async { Future<TxData> confirmSend({required TxData txData}) async {
final senderKeyPair = await _getSenderKeyPair(index: 0); final senderKeyPair = await _getSenderKeyPair(index: 0);
final sender = await stellarSdk.accounts.account(senderKeyPair.accountId); final sender =
await (await stellarSdk).accounts.account(senderKeyPair.accountId);
final address = txData.recipients!.first.address; final address = txData.recipients!.first.address;
final amountToSend = txData.recipients!.first.amount; final amountToSend = txData.recipients!.first.amount;
@ -229,7 +283,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
transaction.sign(senderKeyPair, stellarNetwork); transaction.sign(senderKeyPair, stellarNetwork);
try { try {
final response = await stellarSdk.submitTransaction(transaction); final response = await (await stellarSdk).submitTransaction(transaction);
if (!response.success) { if (!response.success) {
throw Exception("${response.extras?.resultCodes?.transactionResultCode}" throw Exception("${response.extras?.resultCodes?.transactionResultCode}"
" ::: ${response.extras?.resultCodes?.operationsResultCodes}"); " ::: ${response.extras?.resultCodes?.operationsResultCodes}");
@ -256,7 +310,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
@override @override
Future<FeeObject> get fees async { Future<FeeObject> get fees async {
int fee = await _getBaseFee(); final int fee = await _getBaseFee();
return FeeObject( return FeeObject(
numberOfBlocksFast: 1, numberOfBlocksFast: 1,
numberOfBlocksAverage: 1, numberOfBlocksAverage: 1,
@ -294,7 +348,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
stellar.AccountResponse accountResponse; stellar.AccountResponse accountResponse;
try { try {
accountResponse = await stellarSdk.accounts accountResponse = await (await stellarSdk)
.accounts
.account((await getCurrentReceivingAddress())!.value) .account((await getCurrentReceivingAddress())!.value)
.onError((error, stackTrace) => throw error!); .onError((error, stackTrace) => throw error!);
} catch (e) { } catch (e) {
@ -315,7 +370,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
} }
} }
for (stellar.Balance balance in accountResponse.balances) { for (final stellar.Balance balance in accountResponse.balances) {
switch (balance.assetType) { switch (balance.assetType) {
case stellar.Asset.TYPE_NATIVE: case stellar.Asset.TYPE_NATIVE:
final swBalance = Balance( final swBalance = Balance(
@ -352,7 +407,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
@override @override
Future<void> updateChainHeight() async { Future<void> updateChainHeight() async {
try { try {
final height = await stellarSdk.ledgers final height = await (await stellarSdk)
.ledgers
.order(stellar.RequestBuilderOrder.DESC) .order(stellar.RequestBuilderOrder.DESC)
.limit(1) .limit(1)
.execute() .execute()
@ -370,7 +426,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
@override @override
Future<void> updateNode() async { Future<void> updateNode() async {
_updateSdk(); _stellarSdk?.httpClient.close();
_stellarSdk = _getFreshSdk();
} }
@override @override
@ -378,10 +435,11 @@ class StellarWallet extends Bip39Wallet<Stellar> {
try { try {
final myAddress = (await getCurrentReceivingAddress())!; final myAddress = (await getCurrentReceivingAddress())!;
List<TransactionV2> transactionList = []; final List<TransactionV2> transactionList = [];
stellar.Page<stellar.OperationResponse> payments; stellar.Page<stellar.OperationResponse> payments;
try { try {
payments = await stellarSdk.payments payments = await (await stellarSdk)
.payments
.forAccount(myAddress.value) .forAccount(myAddress.value)
.order(stellar.RequestBuilderOrder.DESC) .order(stellar.RequestBuilderOrder.DESC)
.execute(); .execute();
@ -401,7 +459,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
rethrow; rethrow;
} }
} }
for (stellar.OperationResponse response in payments.records!) { for (final stellar.OperationResponse response in payments.records!) {
// PaymentOperationResponse por; // PaymentOperationResponse por;
if (response is stellar.PaymentOperationResponse) { if (response is stellar.PaymentOperationResponse) {
final por = response; final por = response;
@ -431,7 +489,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
final List<OutputV2> outputs = []; final List<OutputV2> outputs = [];
final List<InputV2> inputs = []; final List<InputV2> inputs = [];
OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( final OutputV2 output =
OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: "00", scriptPubKeyHex: "00",
valueStringSats: amount.raw.toString(), valueStringSats: amount.raw.toString(),
addresses: [ addresses: [
@ -439,7 +498,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
], ],
walletOwns: addressTo == myAddress.value, walletOwns: addressTo == myAddress.value,
); );
InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: null, scriptSigHex: null,
scriptSigAsm: null, scriptSigAsm: null,
sequence: null, sequence: null,
@ -459,8 +518,9 @@ class StellarWallet extends Bip39Wallet<Stellar> {
int height = 0; int height = 0;
//Query the transaction linked to the payment, //Query the transaction linked to the payment,
// por.transaction returns a null sometimes // por.transaction returns a null sometimes
stellar.TransactionResponse tx = final stellar.TransactionResponse tx = await (await stellarSdk)
await stellarSdk.transactions.transaction(por.transactionHash!); .transactions
.transaction(por.transactionHash!);
if (tx.hash.isNotEmpty) { if (tx.hash.isNotEmpty) {
fee = tx.feeCharged!; fee = tx.feeCharged!;
@ -511,7 +571,8 @@ class StellarWallet extends Bip39Wallet<Stellar> {
final List<OutputV2> outputs = []; final List<OutputV2> outputs = [];
final List<InputV2> inputs = []; final List<InputV2> inputs = [];
OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( final OutputV2 output =
OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: "00", scriptPubKeyHex: "00",
valueStringSats: amount.raw.toString(), valueStringSats: amount.raw.toString(),
addresses: [ addresses: [
@ -520,7 +581,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
], ],
walletOwns: caor.sourceAccount! == myAddress.value, walletOwns: caor.sourceAccount! == myAddress.value,
); );
InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: null, scriptSigHex: null,
scriptSigAsm: null, scriptSigAsm: null,
sequence: null, sequence: null,
@ -541,8 +602,9 @@ class StellarWallet extends Bip39Wallet<Stellar> {
int fee = 0; int fee = 0;
int height = 0; int height = 0;
final tx = final tx = await (await stellarSdk)
await stellarSdk.transactions.transaction(caor.transactionHash!); .transactions
.transaction(caor.transactionHash!);
if (tx.hash.isNotEmpty) { if (tx.hash.isNotEmpty) {
fee = tx.feeCharged!; fee = tx.feeCharged!;
height = tx.ledger; height = tx.ledger;