mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 03:49:22 +00:00
untested stellar tor listener
This commit is contained in:
parent
65941478b8
commit
dd45c870f6
1 changed files with 90 additions and 28 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue