Merge branch 'staging' into httpsend-error-fix

This commit is contained in:
julian-CStack 2023-09-08 07:28:12 -06:00 committed by GitHub
commit d38d482b87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 573 additions and 145 deletions

View file

@ -289,7 +289,7 @@ class _NewWalletOptionsViewState extends ConsumerState<NewWalletOptionsView> {
child: Center(
child: Text(
"You may add a BIP39 passphrase. This is optional. "
"You will need BOTH you seed and your passphrase to recover the wallet.",
"You will need BOTH your seed and your passphrase to recover the wallet.",
style: Util.isDesktop
? STextStyles.desktopTextExtraSmall(context)
.copyWith(

View file

@ -252,10 +252,17 @@ class _Step4ViewState extends ConsumerState<Step4View> {
},
);
} else {
final memo =
manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet
? model.trade!.payInExtraId.isNotEmpty
? model.trade!.payInExtraId
: null
: null;
txDataFuture = manager.prepareSend(
address: address,
amount: amount,
args: {
"memo": memo,
"feeRate": FeeRateType.average,
// ref.read(feeRateTypeStateProvider)
},
@ -568,6 +575,74 @@ class _Step4ViewState extends ConsumerState<Step4View> {
const SizedBox(
height: 6,
),
if (model.trade!.payInExtraId.isNotEmpty)
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"Memo",
style:
STextStyles.itemSubtitle(context),
),
GestureDetector(
onTap: () async {
final data = ClipboardData(
text:
model.trade!.payInExtraId);
await clipboard.setData(data);
if (mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
message:
"Copied to clipboard",
context: context,
),
);
}
},
child: Row(
children: [
SvgPicture.asset(
Assets.svg.copy,
color: Theme.of(context)
.extension<StackColors>()!
.infoItemIcons,
width: 10,
),
const SizedBox(
width: 4,
),
Text(
"Copy",
style:
STextStyles.link2(context),
),
],
),
),
],
),
const SizedBox(
height: 4,
),
Text(
model.trade!.payInExtraId,
style:
STextStyles.itemSubtitle12(context),
),
],
),
),
if (model.trade!.payInExtraId.isNotEmpty)
const SizedBox(
height: 6,
),
RoundedWhiteContainer(
child: Row(
children: [

View file

@ -268,10 +268,17 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
// if not firo then do normal send
if (shouldSendPublicFiroFunds == null) {
final memo =
manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet
? trade.payInExtraId.isNotEmpty
? trade.payInExtraId
: null
: null;
txDataFuture = manager.prepareSend(
address: address,
amount: amount,
args: {
"memo": memo,
"feeRate": FeeRateType.average,
// ref.read(feeRateTypeStateProvider)
},

View file

@ -850,6 +850,81 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
: const SizedBox(
height: 12,
),
if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx)
RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.all(16)
: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Memo",
style: STextStyles.itemSubtitle(context),
),
isDesktop
? IconCopyButton(
data: trade.payInExtraId,
)
: GestureDetector(
onTap: () async {
final address = trade.payInExtraId;
await Clipboard.setData(
ClipboardData(
text: address,
),
);
if (mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
message: "Copied to clipboard",
context: context,
),
);
}
},
child: Row(
children: [
SvgPicture.asset(
Assets.svg.copy,
width: 12,
height: 12,
color: Theme.of(context)
.extension<StackColors>()!
.infoItemIcons,
),
const SizedBox(
width: 4,
),
Text(
"Copy",
style: STextStyles.link2(context),
),
],
),
),
],
),
const SizedBox(
height: 4,
),
SelectableText(
trade.payInExtraId,
style: STextStyles.itemSubtitle12(context),
),
],
),
),
if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx)
isDesktop
? const _Divider()
: const SizedBox(
height: 12,
),
RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.all(16)

View file

@ -103,6 +103,7 @@ class _SendViewState extends ConsumerState<SendView> {
late TextEditingController noteController;
late TextEditingController onChainNoteController;
late TextEditingController feeController;
late TextEditingController memoController;
late final SendViewAutoFillData? _data;
@ -111,6 +112,9 @@ class _SendViewState extends ConsumerState<SendView> {
final _onChainNoteFocusNode = FocusNode();
final _cryptoFocus = FocusNode();
final _baseFocus = FocusNode();
final _memoFocus = FocusNode();
late final bool isStellar;
Amount? _amountToSend;
Amount? _cachedAmountToSend;
@ -522,10 +526,15 @@ class _SendViewState extends ConsumerState<SendView> {
},
);
} else {
final memo =
manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet
? memoController.text
: null;
txDataFuture = manager.prepareSend(
address: _address!,
amount: amount,
args: {
"memo": memo,
"feeRate": ref.read(feeRateTypeStateProvider),
"satsPerVByte": isCustomFee ? customFeeRate : null,
"UTXOs": (manager.hasCoinControlSupport &&
@ -622,6 +631,7 @@ class _SendViewState extends ConsumerState<SendView> {
walletId = widget.walletId;
clipboard = widget.clipboard;
scanner = widget.barcodeScanner;
isStellar = coin == Coin.stellar || coin == Coin.stellarTestnet;
sendToController = TextEditingController();
cryptoAmountController = TextEditingController();
@ -629,6 +639,7 @@ class _SendViewState extends ConsumerState<SendView> {
noteController = TextEditingController();
onChainNoteController = TextEditingController();
feeController = TextEditingController();
memoController = TextEditingController();
onCryptoAmountChanged = _cryptoAmountChanged;
cryptoAmountController.addListener(onCryptoAmountChanged);
@ -704,12 +715,14 @@ class _SendViewState extends ConsumerState<SendView> {
noteController.dispose();
onChainNoteController.dispose();
feeController.dispose();
memoController.dispose();
_noteFocusNode.dispose();
_onChainNoteFocusNode.dispose();
_addressFocusNode.dispose();
_cryptoFocus.dispose();
_baseFocus.dispose();
_memoFocus.dispose();
super.dispose();
}
@ -1298,6 +1311,88 @@ class _SendViewState extends ConsumerState<SendView> {
),
),
),
const SizedBox(
height: 10,
),
if (isStellar)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
key: const Key("sendViewMemoFieldKey"),
controller: memoController,
readOnly: false,
autocorrect: false,
enableSuggestions: false,
focusNode: _memoFocus,
style: STextStyles.field(context),
onChanged: (_) {
setState(() {});
},
decoration: standardInputDecoration(
"Enter memo (optional)",
_memoFocus,
context,
).copyWith(
contentPadding: const EdgeInsets.only(
left: 16,
top: 6,
bottom: 8,
right: 5,
),
suffixIcon: Padding(
padding: memoController.text.isEmpty
? const EdgeInsets.only(right: 8)
: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: [
memoController.text.isNotEmpty
? TextFieldIconButton(
semanticsLabel:
"Clear Button. Clears The Memo Field Input.",
key: const Key(
"sendViewClearMemoFieldButtonKey"),
onTap: () {
memoController.text = "";
setState(() {});
},
child: const XIcon(),
)
: TextFieldIconButton(
semanticsLabel:
"Paste Button. Pastes From Clipboard To Memo Field Input.",
key: const Key(
"sendViewPasteMemoFieldButtonKey"),
onTap: () async {
final ClipboardData? data =
await clipboard.getData(
Clipboard
.kTextPlain);
if (data?.text != null &&
data!
.text!.isNotEmpty) {
String content =
data.text!.trim();
memoController.text =
content.trim();
setState(() {});
}
},
child: const ClipboardIcon(),
),
],
),
),
),
),
),
),
Builder(
builder: (_) {
final error = _updateInvalidAddressText(
@ -1817,7 +1912,8 @@ class _SendViewState extends ConsumerState<SendView> {
),
child: TextField(
autocorrect: Util.isDesktop ? false : true,
enableSuggestions: Util.isDesktop ? false : true,
enableSuggestions:
Util.isDesktop ? false : true,
maxLength: 256,
controller: onChainNoteController,
focusNode: _onChainNoteFocusNode,
@ -1828,25 +1924,27 @@ class _SendViewState extends ConsumerState<SendView> {
_onChainNoteFocusNode,
context,
).copyWith(
suffixIcon: onChainNoteController.text.isNotEmpty
suffixIcon: onChainNoteController
.text.isNotEmpty
? Padding(
padding:
const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
onChainNoteController.text = "";
});
},
padding:
const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
onChainNoteController
.text = "";
});
},
),
],
),
),
],
),
),
)
)
: null,
),
),
@ -1856,8 +1954,9 @@ class _SendViewState extends ConsumerState<SendView> {
height: 12,
),
Text(
(coin == Coin.epicCash) ? "Local Note (optional)"
: "Note (optional)",
(coin == Coin.epicCash)
? "Local Note (optional)"
: "Note (optional)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),

View file

@ -167,77 +167,77 @@ class HiddenSettings extends StatelessWidget {
// ),
// );
// }),
const SizedBox(
height: 12,
),
Consumer(builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
ref
.read(priceAnd24hChangeNotifierProvider)
.tokenContractAddressesToCheck
.add(
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
ref
.read(priceAnd24hChangeNotifierProvider)
.tokenContractAddressesToCheck
.add(
"0xdAC17F958D2ee523a2206206994597C13D831ec7");
await ref
.read(priceAnd24hChangeNotifierProvider)
.updatePrice();
final x = ref
.read(priceAnd24hChangeNotifierProvider)
.getTokenPrice(
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
print(
"PRICE 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48: $x");
},
child: RoundedWhiteContainer(
child: Text(
"Click me",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
),
);
}),
const SizedBox(
height: 12,
),
Consumer(builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
// final erc20 = Erc20ContractInfo(
// contractAddress: 'some con',
// name: "loonamsn",
// symbol: "DD",
// decimals: 19,
// );
//
// final json = erc20.toJson();
//
// print(json);
//
// final ee = EthContractInfo.fromJson(json);
//
// print(ee);
},
child: RoundedWhiteContainer(
child: Text(
"Click me",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
),
);
}),
// const SizedBox(
// height: 12,
// ),
// Consumer(builder: (_, ref, __) {
// return GestureDetector(
// onTap: () async {
// ref
// .read(priceAnd24hChangeNotifierProvider)
// .tokenContractAddressesToCheck
// .add(
// "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
// ref
// .read(priceAnd24hChangeNotifierProvider)
// .tokenContractAddressesToCheck
// .add(
// "0xdAC17F958D2ee523a2206206994597C13D831ec7");
// await ref
// .read(priceAnd24hChangeNotifierProvider)
// .updatePrice();
//
// final x = ref
// .read(priceAnd24hChangeNotifierProvider)
// .getTokenPrice(
// "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
//
// print(
// "PRICE 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48: $x");
// },
// child: RoundedWhiteContainer(
// child: Text(
// "Click me",
// style: STextStyles.button(context).copyWith(
// color: Theme.of(context)
// .extension<StackColors>()!
// .accentColorDark),
// ),
// ),
// );
// }),
// const SizedBox(
// height: 12,
// ),
// Consumer(builder: (_, ref, __) {
// return GestureDetector(
// onTap: () async {
// // final erc20 = Erc20ContractInfo(
// // contractAddress: 'some con',
// // name: "loonamsn",
// // symbol: "DD",
// // decimals: 19,
// // );
// //
// // final json = erc20.toJson();
// //
// // print(json);
// //
// // final ee = EthContractInfo.fromJson(json);
// //
// // print(ee);
// },
// child: RoundedWhiteContainer(
// child: Text(
// "Click me",
// style: STextStyles.button(context).copyWith(
// color: Theme.of(context)
// .extension<StackColors>()!
// .accentColorDark),
// ),
// ),
// );
// }),
const SizedBox(
height: 12,
),

View file

@ -155,6 +155,23 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
if (ref.watch(desktopExchangeModelProvider
.select((value) => value!.trade?.payInExtraId)) !=
null)
DesktopStepItem(
vertical: true,
label: "Memo",
value: ref.watch(desktopExchangeModelProvider
.select((value) => value!.trade?.payInExtraId)) ??
"Error",
),
if (ref.watch(desktopExchangeModelProvider
.select((value) => value!.trade?.payInExtraId)) !=
null)
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
DesktopStepItem(
label: "Amount",
value:

View file

@ -97,12 +97,16 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
late TextEditingController cryptoAmountController;
late TextEditingController baseAmountController;
// late TextEditingController feeController;
late TextEditingController memoController;
late final SendViewAutoFillData? _data;
final _addressFocusNode = FocusNode();
final _cryptoFocus = FocusNode();
final _baseFocus = FocusNode();
final _memoFocus = FocusNode();
late final bool isStellar;
String? _note;
String? _onChainNote;
@ -326,10 +330,12 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
},
);
} else {
final memo = isStellar ? memoController.text : null;
txDataFuture = manager.prepareSend(
address: _address!,
amount: amount,
args: {
"memo": memo,
"feeRate": ref.read(feeRateTypeStateProvider),
"satsPerVByte": isCustomFee ? customFeeRate : null,
"UTXOs": (manager.hasCoinControlSupport &&
@ -663,6 +669,23 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
}
}
Future<void> pasteMemo() async {
if (memoController.text.isNotEmpty) {
setState(() {
memoController.text = "";
});
} else {
final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain);
if (data?.text != null && data!.text!.isNotEmpty) {
String content = data.text!.trim();
setState(() {
memoController.text = content;
});
}
}
}
void fiatTextFieldOnChanged(String baseAmountString) {
final baseAmount = Amount.tryParseFiatString(
baseAmountString,
@ -762,10 +785,12 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
coin = ref.read(walletsChangeNotifierProvider).getManager(walletId).coin;
clipboard = widget.clipboard;
scanner = widget.barcodeScanner;
isStellar = coin == Coin.stellar || coin == Coin.stellarTestnet;
sendToController = TextEditingController();
cryptoAmountController = TextEditingController();
baseAmountController = TextEditingController();
memoController = TextEditingController();
// feeController = TextEditingController();
onCryptoAmountChanged = _cryptoAmountChanged;
@ -814,11 +839,13 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
sendToController.dispose();
cryptoAmountController.dispose();
baseAmountController.dispose();
memoController.dispose();
// feeController.dispose();
_addressFocusNode.dispose();
_cryptoFocus.dispose();
_baseFocus.dispose();
_memoFocus.dispose();
super.dispose();
}
@ -1367,6 +1394,67 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
}
},
),
if (isStellar)
const SizedBox(
height: 10,
),
if (isStellar)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
minLines: 1,
maxLines: 5,
key: const Key("sendViewMemoFieldKey"),
controller: memoController,
readOnly: false,
autocorrect: false,
enableSuggestions: false,
focusNode: _memoFocus,
onChanged: (_) {
setState(() {});
},
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveText,
height: 1.8,
),
decoration: standardInputDecoration(
"Enter memo (optional)",
_memoFocus,
context,
desktopMed: true,
).copyWith(
contentPadding: const EdgeInsets.only(
left: 16,
top: 11,
bottom: 12,
right: 5,
),
suffixIcon: Padding(
padding: memoController.text.isEmpty
? const EdgeInsets.only(right: 8)
: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TextFieldIconButton(
key: const Key("sendViewPasteMemoButtonKey"),
onTap: pasteMemo,
child: memoController.text.isEmpty
? const ClipboardIcon()
: const XIcon(),
),
],
),
),
),
),
),
),
if (!isPaynymSend)
const SizedBox(
height: 20,

View file

@ -3352,6 +3352,30 @@ class FiroWallet extends CoinServiceAPI
List<Map<String, dynamic>> allTransactions = [];
// some lelantus transactions aren't fetched via wallet addresses so they
// will never show as confirmed in the gui.
final unconfirmedTransactions =
await db.getTransactions(walletId).filter().heightIsNull().findAll();
for (final tx in unconfirmedTransactions) {
final txn = await cachedElectrumXClient.getTransaction(
txHash: tx.txid,
verbose: true,
coin: coin,
);
final height = txn["height"] as int?;
if (height != null) {
// tx was mined
// add to allTxHashes
final info = {
"tx_hash": tx.txid,
"height": height,
"address": tx.address.value?.value,
};
allTxHashes.add(info);
}
}
// final currentHeight = await chainHeight;
for (final txHash in allTxHashes) {

View file

@ -181,6 +181,41 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
return exists;
}
@override
Future<Map<String, dynamic>> prepareSend(
{required String address,
required Amount amount,
Map<String, dynamic>? args}) async {
try {
final feeRate = args?["feeRate"];
var fee = 1000;
if (feeRate is FeeRateType) {
final theFees = await fees;
switch (feeRate) {
case FeeRateType.fast:
fee = theFees.fast;
case FeeRateType.slow:
fee = theFees.slow;
case FeeRateType.average:
default:
fee = theFees.medium;
}
}
Map<String, dynamic> txData = {
"fee": fee,
"address": address,
"recipientAmt": amount,
"memo": args?["memo"] as String?,
};
Logging.instance.log("prepare send: $txData", level: LogLevel.Info);
return txData;
} catch (e, s) {
Logging.instance.log("Error getting fees $e - $s", level: LogLevel.Error);
rethrow;
}
}
@override
Future<String> confirmSend({required Map<String, dynamic> txData}) async {
final secretSeed = await _secureStore.read(key: '${_walletId}_secretSeed');
@ -188,27 +223,33 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
AccountResponse sender =
await stellarSdk.accounts.account(senderKeyPair.accountId);
final amountToSend = txData['recipientAmt'] as Amount;
final memo = txData["memo"] as String?;
//First check if account exists, can be skipped, but if the account does not exist,
// the transaction fee will be charged when the transaction fails.
bool validAccount = await _accountExists(txData['address'] as String);
Transaction transaction;
TransactionBuilder transactionBuilder;
if (!validAccount) {
//Fund the account, user must ensure account is correct
CreateAccountOperationBuilder createAccBuilder =
CreateAccountOperationBuilder(
txData['address'] as String, amountToSend.decimal.toString());
transaction = TransactionBuilder(sender)
.addOperation(createAccBuilder.build())
.build();
transactionBuilder =
TransactionBuilder(sender).addOperation(createAccBuilder.build());
} else {
transaction = TransactionBuilder(sender)
.addOperation(PaymentOperationBuilder(txData['address'] as String,
Asset.NATIVE, amountToSend.decimal.toString())
.build())
.build();
transactionBuilder = TransactionBuilder(sender).addOperation(
PaymentOperationBuilder(txData['address'] as String, Asset.NATIVE,
amountToSend.decimal.toString())
.build());
}
if (memo != null) {
transactionBuilder.addMemo(MemoText(memo));
}
final transaction = transactionBuilder.build();
transaction.sign(senderKeyPair, stellarNetwork);
try {
SubmitTransactionResponse response = await stellarSdk
@ -441,40 +482,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
Future<String?> get mnemonicString =>
_secureStore.read(key: '${_walletId}_mnemonic');
@override
Future<Map<String, dynamic>> prepareSend(
{required String address,
required Amount amount,
Map<String, dynamic>? args}) async {
try {
final feeRate = args?["feeRate"];
var fee = 1000;
if (feeRate is FeeRateType) {
final theFees = await fees;
switch (feeRate) {
case FeeRateType.fast:
fee = theFees.fast;
case FeeRateType.slow:
fee = theFees.slow;
case FeeRateType.average:
default:
fee = theFees.medium;
}
}
Map<String, dynamic> txData = {
"fee": fee,
"address": address,
"recipientAmt": amount,
};
Logging.instance.log("prepare send: $txData", level: LogLevel.Info);
return txData;
} catch (e, s) {
Logging.instance.log("Error getting fees $e - $s", level: LogLevel.Error);
rethrow;
}
}
Future<void> _recoverWalletFromBIP32SeedPhrase({
required String mnemonic,
required String mnemonicPassphrase,
@ -572,14 +579,29 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
try {
List<Tuple2<SWTransaction.Transaction, SWAddress.Address?>>
transactionList = [];
Page<OperationResponse> payments = await stellarSdk.payments
.forAccount(await getAddressSW())
.order(RequestBuilderOrder.DESC)
.execute()
.onError(
(error, stackTrace) => throw ("Could not fetch transactions"));
Page<OperationResponse> payments;
try {
payments = await stellarSdk.payments
.forAccount(await getAddressSW())
.order(RequestBuilderOrder.DESC)
.execute()
.onError((error, stackTrace) => throw error!);
} catch (e) {
if (e is ErrorResponse &&
e.body.contains("The resource at the url requested was not found. "
"This usually occurs for one of two reasons: "
"The url requested is not valid, or no data in our database "
"could be found with the parameters provided.")) {
// probably just doesn't have any history yet or whatever stellar needs
return;
} else {
Logging.instance.log(
"Stellar $walletName $walletId failed to fetch transactions",
level: LogLevel.Warning,
);
rethrow;
}
}
for (OperationResponse response in payments.records!) {
// PaymentOperationResponse por;
if (response is PaymentOperationResponse) {
@ -717,8 +739,29 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
Future<void> updateBalance() async {
try {
AccountResponse accountResponse =
await stellarSdk.accounts.account(await getAddressSW());
AccountResponse accountResponse;
try {
accountResponse = await stellarSdk.accounts
.account(await getAddressSW())
.onError((error, stackTrace) => throw error!);
} catch (e) {
if (e is ErrorResponse &&
e.body.contains("The resource at the url requested was not found. "
"This usually occurs for one of two reasons: "
"The url requested is not valid, or no data in our database "
"could be found with the parameters provided.")) {
// probably just doesn't have any history yet or whatever stellar needs
return;
} else {
Logging.instance.log(
"Stellar $walletName $walletId failed to fetch transactions",
level: LogLevel.Warning,
);
rethrow;
}
}
for (Balance balance in accountResponse.balances) {
switch (balance.assetType) {
case Asset.TYPE_NATIVE: