diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 14b38ae0..47b9cfb3 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -269,51 +269,51 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - app_group_directory: a2613caae8f771366673bd6ec80412b76bbb4fb4 - app_links: 3da4c36b46cac3bf24eb897f1a6ce80bda109874 - connectivity_plus: 2256d3e20624a7749ed21653aafe291a46446fee - device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe + app_group_directory: 7bf9f8f9819ead554de29da7c25fb7a680d6a9a0 + app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0 + connectivity_plus: 18382e7311ba19efcaee94442b23b32507b20695 + device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 Firebase: 374a441a91ead896215703a674d58cdb3e9d772b - firebase_core: 2337982fb78ee4d8d91e608b0a3d4f44346a93c8 - firebase_dynamic_links: 4979f43b85fdbe580099563fe47a0265ae4e622d - firebase_messaging: f3bddfa28c2cad70b3341bf461e987a24efd28d6 + firebase_core: feb37e79f775c2bd08dd35e02d83678291317e10 + firebase_dynamic_links: ca97a0fa34c44aeb1baf7ee017bd12200049695b + firebase_messaging: e2f0ba891b1509668c07f5099761518a5af8fe3c FirebaseCore: 48b0dd707581cf9c1a1220da68223fb0a562afaa FirebaseCoreInternal: d98ab91e2d80a56d7b246856a8885443b302c0c2 FirebaseDynamicLinks: bc4e79f608ce4ee066125695f20f2d9fc137d29e FirebaseInstallations: efc0946fc756e4d22d8113f7c761948120322e8c FirebaseMessaging: e1aca1fcc23e8b9eddb0e33f375ff90944623021 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_breez_liquid: 71c144f4bcd178ea93c86cb9f8c6250b2fad47af - flutter_fgbg: d3da78df78454b1808f0829a5da9cd17dfe16444 - flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 - flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619 - flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 + flutter_breez_liquid: 8306e7e1867337fbecadf2b0f538270dc282ea94 + flutter_fgbg: 31c0d1140a131daea2d342121808f6aa0dcd879d + flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 + flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 + flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleMLKit: eff9e23ec1d90ea4157a1ee2e32a4f610c5b3318 GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8 GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 - image_cropper: 5f162dcf988100dc1513f9c6b7eb42cd6fbf9156 - image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a + image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 - local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 + local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 MLImage: 0ad1c5f50edd027672d8b26b0fee78a8b4a0fc56 MLKitBarcodeScanning: 0a3064da0a7f49ac24ceb3cb46a5bc67496facd2 MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e - mobile_scanner: af8f71879eaba2bbcb4d86c6a462c3c0e7f23036 + mobile_scanner: fd0054c52ede661e80bf5a4dea477a2467356bee nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 ObjcExceptionBridging: d3d37d62981bb7f252ecb31b62d7e23a96bbfb8a OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a - shared_preference_app_group: 7422922a188e05cf680a656e18e2786dcb5c58b3 - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 - sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f + shared_preference_app_group: 46aee3873e1da581d4904bece9876596d7f66725 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 - url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe XCGLogger: 399c5885210b4e2ad79d9f7a29b105d672ef724f PODFILE CHECKSUM: 0ce493dcb0f7bebb017b9d87555c839c9685fa8b diff --git a/lib/cubit/account/account_state.dart b/lib/cubit/account/account_state.dart index 91f7a2ce..88caf67e 100644 --- a/lib/cubit/account/account_state.dart +++ b/lib/cubit/account/account_state.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:breez_liquid/breez_liquid.dart'; import 'package:logging/logging.dart'; +import 'package:l_breez/models/asset_extension.dart'; final Logger _logger = Logger('AccountState'); @@ -71,6 +72,7 @@ extension WalletInfoToJson on WalletInfo { 'pendingReceiveSat': pendingReceiveSat.toString(), 'fingerprint': fingerprint, 'pubkey': pubkey, + 'assetBalances': assetBalances.map((AssetBalance assetBalance) => assetBalance.toJson()).toList(), }; } } @@ -97,6 +99,11 @@ extension WalletInfoFromJson on WalletInfo { pendingReceiveSat: BigInt.parse(json['pendingReceiveSat'] as String), fingerprint: json['fingerprint'] as String, pubkey: json['pubkey'] as String, + assetBalances: json['assetBalances'] != null + ? (json['assetBalances'] as List) + .map((dynamic json) => AssetBalanceFromJson.fromJson(json)) + .toList() + : [], ); } } diff --git a/lib/cubit/chain_swap/chain_swap_cubit.dart b/lib/cubit/chain_swap/chain_swap_cubit.dart index 5cc7d956..e5dc132c 100644 --- a/lib/cubit/chain_swap/chain_swap_cubit.dart +++ b/lib/cubit/chain_swap/chain_swap_cubit.dart @@ -78,8 +78,8 @@ class ChainSwapCubit extends Cubit { List>.generate(3, (int index) async { final PayAmount payAmount = isDrain ? const PayAmount_Drain() - : PayAmount_Receiver( - amountSat: BigInt.from(amountSat), + : PayAmount_Bitcoin( + receiverAmountSat: BigInt.from(amountSat), ); final PreparePayOnchainRequest preparePayOnchainRequest = PreparePayOnchainRequest( amount: payAmount, diff --git a/lib/cubit/payments/models/payment/payment_filters.dart b/lib/cubit/payments/models/payment/payment_filters.dart index f42bc467..c5647d40 100644 --- a/lib/cubit/payments/models/payment/payment_filters.dart +++ b/lib/cubit/payments/models/payment/payment_filters.dart @@ -7,11 +7,13 @@ class PaymentFilters implements Exception { final List? filters; final int? fromTimestamp; final int? toTimestamp; + final String? assetTicker; PaymentFilters({ this.filters = PaymentType.values, this.fromTimestamp, this.toTimestamp, + this.assetTicker, }); PaymentFilters.initial() : this(); @@ -20,15 +22,19 @@ class PaymentFilters implements Exception { bool get hasDateFilters => fromTimestamp != null || toTimestamp != null; + bool get hasAssetFilters => assetTicker != null; + PaymentFilters copyWith({ List? filters, int? fromTimestamp, int? toTimestamp, + String? assetTicker, }) { return PaymentFilters( filters: filters ?? this.filters, fromTimestamp: fromTimestamp, toTimestamp: toTimestamp, + assetTicker: assetTicker, ); } @@ -36,6 +42,7 @@ class PaymentFilters implements Exception { return PaymentFilters( fromTimestamp: json['fromTimestamp'], toTimestamp: json['toTimestamp'], + assetTicker: json['assetTicker'], ); } @@ -44,6 +51,7 @@ class PaymentFilters implements Exception { 'filters': filters.toString(), 'fromTimestamp': fromTimestamp, 'toTimestamp': toTimestamp, + 'assetTicker': assetTicker, }; } @@ -55,6 +63,7 @@ class PaymentFilters implements Exception { filters?.map((PaymentType type) => type.hashCode).toList() ?? [], fromTimestamp, toTimestamp, + assetTicker, ); @override @@ -63,6 +72,7 @@ class PaymentFilters implements Exception { other is PaymentFilters && listEquals(filters, other.filters) && fromTimestamp == other.fromTimestamp && - toTimestamp == other.toTimestamp; + toTimestamp == other.toTimestamp && + assetTicker == other.assetTicker; } } diff --git a/lib/cubit/payments/payments_cubit.dart b/lib/cubit/payments/payments_cubit.dart index 1e09d3bd..7bfbef60 100644 --- a/lib/cubit/payments/payments_cubit.dart +++ b/lib/cubit/payments/payments_cubit.dart @@ -56,8 +56,8 @@ class PaymentsCubit extends Cubit with HydratedMixin with HydratedMixin with HydratedMixin payments; @@ -16,8 +17,18 @@ class PaymentsState { List? payments, PaymentFilters? paymentFilters, }) { + // This is a workaround to only include BTC assets in the unfiltered payments. + // If Misty is to support multi-assets then this prefilter should be removed. + final List? prefilteredPayments = payments?.where((PaymentData paymentData) { + final String? paymentAssetTicker = paymentData.details.map( + liquid: (PaymentDetails_Liquid details) => details.assetInfo?.ticker ?? '', + orElse: () => null, + ); + return paymentAssetTicker == null || paymentAssetTicker == 'BTC'; + }).toList(); + return PaymentsState( - payments: payments ?? this.payments, + payments: prefilteredPayments ?? this.payments, paymentFilters: paymentFilters ?? this.paymentFilters, ); } @@ -41,7 +52,16 @@ class PaymentsState { final bool passTypeFilter = typeFilterSet == null || typeFilterSet.contains(paymentData.paymentType.name); - return passDateFilter && passTypeFilter; + final String? paymentAssetTicker = paymentData.details.map( + liquid: (PaymentDetails_Liquid details) => details.assetInfo?.ticker ?? '', + orElse: () => null, + ); + + final bool passAssetFilter = !paymentFilters.hasAssetFilters || + paymentAssetTicker == null || + paymentAssetTicker == paymentFilters.assetTicker; + + return passDateFilter && passTypeFilter && passAssetFilter; }, ).toList(); } diff --git a/lib/models/asset_extension.dart b/lib/models/asset_extension.dart new file mode 100644 index 00000000..cc7dc66d --- /dev/null +++ b/lib/models/asset_extension.dart @@ -0,0 +1,49 @@ +import 'package:flutter_breez_liquid/flutter_breez_liquid.dart'; + +extension AssetBalanceToJson on AssetBalance { + Map toJson() { + return { + 'assetId': assetId, + 'balanceSat': balanceSat.toString(), + 'name': name, + 'ticker': ticker, + 'balance': balance?.toString(), + }; + } +} + +extension AssetBalanceFromJson on AssetBalance { + static AssetBalance fromJson(Map json) { + return AssetBalance( + assetId: json['assetId'] as String, + balanceSat: BigInt.parse(json['balanceSat'] as String), + name: json['name'] as String?, + ticker: json['ticker'] as String?, + balance: json['balance'] != null ? double.parse(json['balance'] as String) : null, + ); + } +} + +extension AssetInfoToJson on AssetInfo { + Map toJson() { + return { + 'name': name, + 'ticker': ticker, + 'amount': amount.toString(), + }; + } +} + +extension AssetInfoFromJson on AssetInfo { + static AssetInfo? fromJson(Map? json) { + if (json == null) { + return null; + } + + return AssetInfo( + name: json['name'] as String, + ticker: json['ticker'] as String, + amount: double.parse(json['amount'] as String), + ); + } +} diff --git a/lib/models/payment_details_extension.dart b/lib/models/payment_details_extension.dart index a48c001a..cbdc9487 100644 --- a/lib/models/payment_details_extension.dart +++ b/lib/models/payment_details_extension.dart @@ -1,4 +1,5 @@ import 'package:flutter_breez_liquid/flutter_breez_liquid.dart'; +import 'package:l_breez/models/asset_extension.dart'; import 'package:l_breez/utils/date.dart'; // TODO(erdemyerebasmaz): Ensure that any changes to [PaymentDetails] are reflected here on each extension. @@ -38,6 +39,8 @@ extension PaymentDetailsToJson on PaymentDetails { 'type': 'liquid', 'destination': details.destination, 'description': details.description, + 'assetId': details.assetId, + 'assetInfo': details.assetInfo?.toJson(), }, bitcoin: (PaymentDetails_Bitcoin details) => { 'type': 'bitcoin', @@ -71,6 +74,8 @@ extension PaymentDetailsFromJson on PaymentDetails { return PaymentDetails.liquid( destination: json['destination'] as String, description: json['description'] as String, + assetId: json['assetId'] as String, + assetInfo: AssetInfoFromJson.fromJson(json['assetInfo']), ); case 'bitcoin': return PaymentDetails.bitcoin( @@ -87,6 +92,8 @@ extension PaymentDetailsFromJson on PaymentDetails { return PaymentDetails.liquid( destination: json['destination'] as String, description: json['description'] as String, + assetId: json['assetId'] as String, + assetInfo: AssetInfoFromJson.fromJson(json['assetInfo']), ); } } @@ -107,7 +114,9 @@ extension PaymentDetailsExtension on PaymentDetails { o.refundTxAmountSat == (this as PaymentDetails_Lightning).refundTxAmountSat, liquid: (PaymentDetails_Liquid o) => o.destination == (this as PaymentDetails_Liquid).destination && - o.description == (this as PaymentDetails_Liquid).description, + o.description == (this as PaymentDetails_Liquid).description && + o.assetId == (this as PaymentDetails_Liquid).assetId && + o.assetInfo == (this as PaymentDetails_Liquid).assetInfo, bitcoin: (PaymentDetails_Bitcoin o) => o.swapId == (this as PaymentDetails_Bitcoin).swapId && o.description == (this as PaymentDetails_Bitcoin).description && @@ -131,7 +140,7 @@ extension PaymentDetailsHashCode on PaymentDetails { o.refundTxId, o.refundTxAmountSat, ), - liquid: (PaymentDetails_Liquid o) => Object.hash(o.destination, o.description), + liquid: (PaymentDetails_Liquid o) => Object.hash(o.destination, o.description, o.assetId, o.assetInfo), bitcoin: (PaymentDetails_Bitcoin o) => Object.hash(o.swapId, o.description, o.autoAcceptedFees, o.refundTxId, o.refundTxAmountSat), orElse: () => 0, diff --git a/packages/breez_sdk_liquid/lib/src/model/config_extension.dart b/packages/breez_sdk_liquid/lib/src/model/config_extension.dart index 058bf345..59e8f5dc 100644 --- a/packages/breez_sdk_liquid/lib/src/model/config_extension.dart +++ b/packages/breez_sdk_liquid/lib/src/model/config_extension.dart @@ -13,6 +13,7 @@ extension ConfigCopyWith on Config { String? breezApiKey, List? externalInputParsers, String? syncServiceUrl, + List? assetMetadata, }) { return Config( liquidElectrumUrl: liquidElectrumUrl ?? this.liquidElectrumUrl, @@ -27,6 +28,7 @@ extension ConfigCopyWith on Config { externalInputParsers: externalInputParsers ?? this.externalInputParsers, syncServiceUrl: syncServiceUrl ?? this.syncServiceUrl, useDefaultExternalInputParsers: true, + assetMetadata: assetMetadata ?? this.assetMetadata, ); } }