From 810ca894dc7dff54f04e07091e79f9d2c23813f6 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 18 Jul 2024 17:13:29 +0330 Subject: [PATCH 01/45] fix: Date parse error --- .../bluetooth/blueberry_ring/utils/blueberry_configs.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart index e260a5b8..6dcc2e70 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart @@ -152,7 +152,8 @@ class BlueberryResolves { } int parseDate(List data) { - final parts = BlueberryCommandsUtils.radix16bcd(data); + // 200x24-0x06-0x05 0x06:0x39:0x02 + final parts = BlueberryCommandsUtils.radix16bcd(data, no0x: true); final ymd = '20${parts[0]}-${parts[1]}-${parts[2]}'; final hms = '${parts[3]}:${parts[4]}:${parts[5]}'; final date = DateTime.parse('$ymd $hms'); From 8554fa8b2dc0342c5781bac92f3ccde1e8141dc3 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 18 Jul 2024 17:14:07 +0330 Subject: [PATCH 02/45] fix: uncomment notifications page --- .../notifications/notificaitons_page.dart | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart index 45716472..dbc3f776 100644 --- a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart +++ b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart @@ -289,53 +289,53 @@ class NotificationsPage extends HookConsumerWidget { notificationsState .periodicalCallData!.expectedEpochOccurrenceEnabled, ), - // const SizedBox(height: Sizes.spaceXLarge), - // MXCSwitchRowItem( - // title: translate('activity_reminder'), - // value: notificationsState - // .periodicalCallData!.activityReminderEnabled, - // onChanged: notificationsPresenter.changeActivityReminderEnabled, - // enabled: isSettingsChangeEnabled, - // textTrailingWidget: MXCInformationButton( - // texts: getBlueberryRingServiceInfo(context), - // ), - // titleStyle: FontTheme.of(context).h6(), - // ), - // const SizedBox(height: Sizes.spaceXLarge), - // MXCSwitchRowItem( - // title: translate('sleep_insight'), - // value: - // notificationsState.periodicalCallData!.sleepInsightEnabled, - // onChanged: notificationsPresenter.changeSleepInsightEnabled, - // enabled: isSettingsChangeEnabled, - // textTrailingWidget: MXCInformationButton( - // texts: getBlueberryRingServiceInfo(context), - // ), - // titleStyle: FontTheme.of(context).h6(), - // ), - // const SizedBox(height: Sizes.spaceXLarge), - // MXCSwitchRowItem( - // title: translate('heart_alert'), - // value: notificationsState.periodicalCallData!.heartAlertEnabled, - // onChanged: notificationsPresenter.changeHeartAlertEnabled, - // enabled: isSettingsChangeEnabled, - // textTrailingWidget: MXCInformationButton( - // texts: getBlueberryRingServiceInfo(context), - // ), - // titleStyle: FontTheme.of(context).h6(), - // ), - // const SizedBox(height: Sizes.spaceXLarge), - // MXCSwitchRowItem( - // title: translate('low_battery'), - // value: notificationsState.periodicalCallData!.lowBatteryEnabled, - // onChanged: notificationsPresenter.changeLowBatteryEnabled, - // enabled: isSettingsChangeEnabled, - // textTrailingWidget: MXCInformationButton( - // texts: getBlueberryRingServiceInfo(context), - // ), - // titleStyle: FontTheme.of(context).h6(), - // ), - // const SizedBox(height: Sizes.spaceXLarge), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('activity_reminder'), + value: notificationsState + .periodicalCallData!.activityReminderEnabled, + onChanged: notificationsPresenter.changeActivityReminderEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: getBlueberryRingServiceInfo(context), + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('sleep_insight'), + value: + notificationsState.periodicalCallData!.sleepInsightEnabled, + onChanged: notificationsPresenter.changeSleepInsightEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: getBlueberryRingServiceInfo(context), + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('heart_alert'), + value: notificationsState.periodicalCallData!.heartAlertEnabled, + onChanged: notificationsPresenter.changeHeartAlertEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: getBlueberryRingServiceInfo(context), + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('low_battery'), + value: notificationsState.periodicalCallData!.lowBatteryEnabled, + onChanged: notificationsPresenter.changeLowBatteryEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: getBlueberryRingServiceInfo(context), + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), // const SizedBox(height: Sizes.spaceNormal), // MXCSwitchRowItem( // title: translate('daily_earnings'), From b18bfdf36dd3d374fce996b1f807d552cb741c6a Mon Sep 17 00:00:00 2001 From: reasje Date: Sun, 21 Jul 2024 16:03:05 +0330 Subject: [PATCH 03/45] fix: Handle bluetooth adapter being off --- .../packages/bluetooth/blue_plus/bluetooth_use_case.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart index 2a9002b4..6c8f7e79 100644 --- a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart +++ b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart @@ -49,8 +49,13 @@ class BluetoothUseCase extends ReactiveUseCase { // usually start scanning, connecting, etc isScanningListener(); initScannerListener(); - } else { + } else if (state == BluetoothAdapterState.unauthorized || + state == BluetoothAdapterState.unavailable || + state == BluetoothAdapterState.off || + state == BluetoothAdapterState.unknown) { // show an error to the user, etc + cancelIsScanningListener(); + _cancelScannerListen(); } }); } From 24b5b2f9e5692acd32df6dbb2a4977d0883df161 Mon Sep 17 00:00:00 2001 From: reasje Date: Sun, 21 Jul 2024 16:03:43 +0330 Subject: [PATCH 04/45] fix: Disconnect blueberry when dapp closed --- .../dapps/subfeatures/open_dapp/open_dapp_presenter.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 28418532..f54274b6 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -85,9 +85,15 @@ class OpenDAppPresenter extends CompletePresenter { @override Future dispose() { characteriticListnerTimer?.cancel(); + closeBlueberryConnection(); return super.dispose(); } + // Disconnects from Blueberry If there a selected device. + void closeBlueberryConnection() { + state.selectedScanResult?.device.disconnect(); + } + void onWebViewCreated(InAppWebViewController controller) async { notify(() => state.webviewController = controller); updateCurrentUrl(null); From a2b7a1adca93b43d69ceb06c451aeeecafc591cb Mon Sep 17 00:00:00 2001 From: reasje Date: Sun, 21 Jul 2024 17:58:31 +0330 Subject: [PATCH 05/45] fix: callHandlerWrapper mechanism --- assets/js/bluetooth/bluetooth.js | 46 ++++++++++--------- .../open_dapp/open_dapp_presenter.dart | 31 ++++++------- packages/shared | 2 +- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/assets/js/bluetooth/bluetooth.js b/assets/js/bluetooth/bluetooth.js index 5a1201d7..6af8e4f5 100644 --- a/assets/js/bluetooth/bluetooth.js +++ b/assets/js/bluetooth/bluetooth.js @@ -33,7 +33,7 @@ class BluetoothDevice extends EventTarget { async watchAdvertisements() { console.log("BluetoothRemoteGATTServer:watchAdvertisements "); - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothDevice.watchAdvertisements" ); console.log( @@ -45,7 +45,7 @@ class BluetoothDevice extends EventTarget { async forget() { console.log("BluetoothRemoteGATTServer:forget "); - const response = await window.axs.callHandler("BluetoothDevice.forget"); + const response = await window.axs?.callHandlerWrapper("BluetoothDevice.forget"); console.log( "BluetoothRemoteGATTServer:forget ", JSON.stringify(response, null, 2) @@ -63,7 +63,7 @@ class BluetoothRemoteGATTServer extends EventTarget { async connect() { console.log("BluetoothRemoteGATTServer:connect "); - const response = await window.axs?.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTServer.connect", {} ); @@ -78,13 +78,13 @@ class BluetoothRemoteGATTServer extends EventTarget { async disconnect() { console.log("BluetoothRemoteGATTServer:disconnect "); - await window.axs.callHandler("BluetoothRemoteGATTServer.disconnect", {}); + await window.axs?.callHandlerWrapper("BluetoothRemoteGATTServer.disconnect", {}); } async getPrimaryService(service) { console.log("BluetoothRemoteGATTServer:getPrimaryService ", service); const data = { service: service }; - const response = await window.axs?.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTServer.getPrimaryService", data ); @@ -104,7 +104,7 @@ class BluetoothRemoteGATTServer extends EventTarget { async getPrimaryServices(service) { console.log("BluetoothRemoteGATTServer:getPrimaryServices ", service); const data = { service: service }; - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTServer.getPrimaryServices", data ); @@ -128,7 +128,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { serviceUUID: this.service.uuid, descriptor: descriptor, }; - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.getDescriptor", data ); @@ -146,7 +146,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { descriptor: descriptor, }; - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.getDescriptors", data ); @@ -156,7 +156,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { async readValue() { console.log("BluetoothRemoteGATTCharacteristic:readValue"); const data = { this: this.uuid, serviceUUID: this.service.uuid }; - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.readValue", data ); @@ -182,7 +182,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { value: value, }; - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.writeValue", data ); @@ -192,9 +192,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { JSON.stringify(response, null, 2) ); - if (response.error !== undefined && response.error === true) { - throw new Error("Error while writing value."); - } + return {}; } async writeValueWithResponse(value) { @@ -208,10 +206,12 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { value: value, }; - await window.axs.callHandler( + await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.writeValueWithResponse", data ); + + return {}; } async writeValueWithoutResponse(value) { @@ -225,17 +225,19 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { value: value, }; - await window.axs.callHandler( + await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.writeValueWithoutResponse", data ); + + return {}; } async startNotifications() { console.log("BluetoothRemoteGATTCharacteristic:startNotifications"); const data = { this: this.uuid, serviceUUID: this.service.uuid }; - await window.axs.callHandler( + await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.startNotifications", data ); @@ -246,7 +248,7 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { console.log("BluetoothRemoteGATTCharacteristic:stopNotifications"); const data = { this: this.uuid, serviceUUID: this.service.uuid }; - await window.axs.callHandler( + await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTCharacteristic.stopNotifications", data ); @@ -273,7 +275,7 @@ class BluetoothRemoteGATTService extends EventTarget { characteristic ); let data = { this: this.uuid, characteristic: characteristic }; - const response = await window.axs?.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTService.getCharacteristic", data ); @@ -296,7 +298,7 @@ class BluetoothRemoteGATTService extends EventTarget { "BluetoothRemoteGATTService:getCharacteristics ", characteristic ); - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTService.getCharacteristics", { this: "$uuid", characteristic: characteristic } ); @@ -305,7 +307,7 @@ class BluetoothRemoteGATTService extends EventTarget { async getIncludedService(service) { console.log("BluetoothRemoteGATTService:getIncludedService ", service); - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTService.getIncludedService", { this: "$uuid", service: service } ); @@ -314,7 +316,7 @@ class BluetoothRemoteGATTService extends EventTarget { async getIncludedServices(service) { console.log("BluetoothRemoteGATTService:getIncludedServices ", service); - const response = await window.axs.callHandler( + const response = await window.axs?.callHandlerWrapper( "BluetoothRemoteGATTService.getIncludedServices", { this: "$uuid", service: service } ); @@ -336,7 +338,7 @@ class AXSBluetooth { async requestDevice(options) { console.log("AXSBluetooth:requestDevice ", options); - const response = await window.axs?.callHandler("requestDevice", options); + const response = await window.axs?.callHandlerWrapper("requestDevice", options); const gatt = new BluetoothRemoteGATTServer( response.gatt.device, diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index f54274b6..59546679 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -815,7 +815,8 @@ class OpenDAppPresenter extends CompletePresenter { Future> handleBluetoothRemoteGATTCharacteristicStartNotifications( Map data) async { - collectLog('handleBluetoothRemoteGATTCharacteristicStartNotifications : $data'); + collectLog( + 'handleBluetoothRemoteGATTCharacteristicStartNotifications : $data'); final selectedService = await getSelectedService(data['serviceUUID']); final selectedCharacteristic = getSelectedCharacteristic(data['this'], selectedService); @@ -832,7 +833,8 @@ class OpenDAppPresenter extends CompletePresenter { Future> handleBluetoothRemoteGATTCharacteristicStopNotifications( Map data) async { - collectLog('handleBluetoothRemoteGATTCharacteristicStopNotifications : $data'); + collectLog( + 'handleBluetoothRemoteGATTCharacteristicStopNotifications : $data'); final selectedService = await getSelectedService(data['serviceUUID']); final selectedCharacteristic = getSelectedCharacteristic(data['this'], selectedService); @@ -852,19 +854,16 @@ class OpenDAppPresenter extends CompletePresenter { final selectedService = await getSelectedService(data['serviceUUID']); final selectedCharacteristic = getSelectedCharacteristic(data['this'], selectedService); - final value = Uint8List.fromList(List.from((data['value'] as Map).values.toList())); + final value = Uint8List.fromList(List.from( + (data['value'] as Map).values.toList())); - try { - collectLog('handleWrites:value $value'); - if (withResponse) { - await selectedCharacteristic.write(value); - } else { - await selectedCharacteristic.write(value, withoutResponse: true); - } - return {}; - } catch (e) { - return {'error': 'true'}; + collectLog('handleWrites:value $value'); + if (withResponse) { + await selectedCharacteristic.write(value); + } else { + await selectedCharacteristic.write(value, withoutResponse: true); } + return {}; } Future> @@ -909,14 +908,10 @@ class OpenDAppPresenter extends CompletePresenter { blue_plus.BluetoothCharacteristic characteristic, ) async { await characteristic.setNotifyValue(true); - // characteriticListnerTimer = Timer.periodic(const Duration(seconds: 5), (timer) { - // characteristic.read(); - // }); characteristicValueStreamSubscription = characteristic.lastValueStream.listen((event) async { final uInt8List = Uint8List.fromList(event); - print(uInt8List); collectLog('characteristicValueStreamSubscription:event $event'); collectLog( 'characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}'); @@ -1012,7 +1007,7 @@ class OpenDAppPresenter extends CompletePresenter { status: AXSJSChannelResponseStatus.failed, data: null, message: e.toString()); - return response.toMap((data) => {'message': e.toString()}); + return response.toMap((data) => {'message': e}); } } diff --git a/packages/shared b/packages/shared index 7f19ffe7..09fe073a 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit 7f19ffe7fd19b885d5d297ae47cc9f3ad09b35a6 +Subproject commit 09fe073aa4e17559f95654da0e8248d307b3279c From e7879a49f6a4005624f01f8a1e5068fd866d15bc Mon Sep 17 00:00:00 2001 From: reasje Date: Sun, 21 Jul 2024 17:58:57 +0330 Subject: [PATCH 06/45] fix: Uninitialized error stream --- .../packages/bluetooth/blue_plus/bluetooth_use_case.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart index 6c8f7e79..12efc251 100644 --- a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart +++ b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart @@ -33,9 +33,9 @@ class BluetoothUseCase extends ReactiveUseCase { final ChainConfigurationUseCase _chainConfigurationUseCase; final AuthUseCase _authUseCase; - late StreamSubscription>? scannerListener; - late StreamSubscription? stateListener; - late StreamSubscription? isScanningStateListener; + StreamSubscription>? scannerListener; + StreamSubscription? stateListener; + StreamSubscription? isScanningStateListener; late final ValueStream isScanning = reactive(false); late final ValueStream bluetoothStatus = From 3a1fd71a68850d07c0e2d93cc1771b41ad7a34f2 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 23 Jul 2024 09:00:18 +0330 Subject: [PATCH 07/45] fix: Remove date specific checks --- ...ing_background_notifications_use_case.dart | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart index 683dec96..7973340c 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart @@ -27,7 +27,8 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkActivityReminder() async { final data = await _blueberryRingUseCase.readSteps(); - collectLog('checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); + collectLog( + 'checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); // Get spteps data from cache and compare // If steps is below a certain number then show a // Below 5000 @@ -40,7 +41,8 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { now.month == lastDate.month && now.day == lastDate.day; - if (isToday && latestData.step < 5000) { + // isToday && + if (latestData.step < 5000) { AXSNotification().showNotification( cTranslate('activity_reminder'), cTranslate('blueberry_ring_inactive_alert_text'), @@ -50,26 +52,29 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkSleepInsight() async { final data = await _blueberryRingUseCase.readSleep(); - collectLog('checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); + collectLog( + 'checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); // If sleeps is below standard level // loop throug all and get average final now = DateTime.now(); final todaysData = data.where((element) { - final date = DateTime.fromMillisecondsSinceEpoch( - element.date * 1000, - ); - final isToday = now.year == date.year && - now.month == date.month && - now.day == date.day; - return isToday; + // final date = DateTime.fromMillisecondsSinceEpoch( + // element.date * 1000, + // ); + // final isToday = now.year == date.year && + // now.month == date.month && + // now.day == date.day; + // return isToday; + return true; }); if (todaysData.isEmpty) { return; } - final isNormal = BlueberryRingDataAnalyzer.isSleepQualityNormal(todaysData.map((e) => e.value).toList()); + final isNormal = BlueberryRingDataAnalyzer.isSleepQualityNormal( + todaysData.map((e) => e.value).toList()); if (!isNormal) { AXSNotification().showNotification( @@ -92,7 +97,8 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { now.month == lastDate.month && now.day == lastDate.day; - if (isToday && latestData.value >= 100) { + // isToday && + if (latestData.value >= 100) { AXSNotification().showNotification( cTranslate('heart_alert'), cTranslate('blueberry_ring_heart_rate_alert_text'), From 3e120e6ded4dc2620e905ddd10346a37ac79c4ee Mon Sep 17 00:00:00 2001 From: Sanghamitra Bhowmick <93600163+SanghamitraBhowmick1993@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:26:21 +0530 Subject: [PATCH 08/45] Update pubspec.yaml --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index b266f44b..cdbfb94a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.4.7 +version: 2.4.8 environment: sdk: ">=2.19.0 <3.0.0" From a05538341346c66149cc62e50079c8c1797dfaf0 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 24 Jul 2024 11:04:29 +0330 Subject: [PATCH 09/45] config: IOS config sync task --- ios/Runner/Info.plist | 297 +++++++++++++++++++++--------------------- 1 file changed, 149 insertions(+), 148 deletions(-) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 606a22f7..9c2bab40 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,156 +1,157 @@ - - BGTaskSchedulerPermittedIdentifiers - - com.transistorsoft.fetch - com.mxc.axswallet.notificationsTask - com.mxc.axswallet.wifiHooksTask - com.mxc.axswallet.minerAutoClaimTask - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - AXS - CFBundleDocumentTypes - - - CFBundleTypeName - FlSharedLink - LSHandlerRank - Default - LSItemContentTypes - - public.file-url - public.image - public.text - public.url - public.data - - - - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLocalizations - - en - zh_TW - zh_CN - zh_HK - ko - ja - vi - ru - tr - de - es - pt - tl - id - it - fr - - CFBundleName - axs - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSApplicationQueriesSchemes - - tg - weixin - wechat - googlegmail - x-dispatch - readdle-spark - airmail - ms-outlook - ymail - fastmail - superhuman - protonmail - - LSRequiresIPhoneOS - - LSSupportsOpeningDocumentsInPlace - No - NSAppTransportSecurity + + BGTaskSchedulerPermittedIdentifiers + + com.transistorsoft.fetch + com.mxc.axswallet.notificationsTask + com.mxc.axswallet.wifiHooksTask + com.mxc.axswallet.minerAutoClaimTask + com.mxc.axswallet.blueberryAutoSyncTask + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + AXS + CFBundleDocumentTypes + - NSAllowsArbitraryLoads - + CFBundleTypeName + FlSharedLink + LSHandlerRank + Default + LSItemContentTypes + + public.file-url + public.image + public.text + public.url + public.data + - NSAppleMusicUsageDescription - Would you allow AXS Wallet to use the Media Library? - NSBluetoothPeripheralUsageDescription - Would you allow AXS Wallet to use the Bluetooth? - NSCalendarsUsageDescription - Would you allow AXS Wallet to use the Calendar? - NSCameraUsageDescription - AXS Wallet needs access to your camera when the app is in use for services such as RWA minting. Image data is not saved or shared with any third parties. - NSFaceIDUsageDescription - AXS Wallet needs access to your Biometric data when the app is in use for authentication only. Your Biometric data is not saved or shared with any third parties. - NSLocationAlwaysAndWhenInUseUsageDescription - AXS Wallet needs access to your location for features such as Wi-Fi hooks while the app is in use or running in the background. Your location data is not saved or shared with any third parties. - NSLocationAlwaysUsageDescription - AXS Wallet requires access to your location at all times for services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. - NSLocationUsageDescription - AXS Wallet needs access to your location to provide services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. - NSLocationWhenInUseUsageDescription - AXS Wallet needs access to your location when the app is in use for services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. - NSMotionUsageDescription - Would you allow AXS Wallet to use the Motion? - NSPhotoLibraryAddUsageDescription - AXS Wallet needs access to your photos to save images such as RWA. Your photos are not saved or shared with any third parties. - NSPhotoLibraryUsageDescription - AXS Wallet needs access to your photos when the app is in use for services such as RWA minting. Your photos are not saved or shared with any third parties. - NSSpeechRecognitionUsageDescription - Would you allow AXS Wallet to use the Speech Recognition? - PermissionGroupNotification - Would you allow AXS Wallet to use the Notification? - NSBluetoothAlwaysUsageDescription - AXS Wallet needs access to your Bluetooth when the app is in use or running in the background for services such as BluberryRing. Blutooth data is not saved or shared with any third parties. - UIApplicationSupportsIndirectInputEvents - - UIBackgroundModes - - fetch - location - processing - remote-notification - bluetooth-central - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - UISupportsDocumentBrowser + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLocalizations + + en + zh_TW + zh_CN + zh_HK + ko + ja + vi + ru + tr + de + es + pt + tl + id + it + fr + + CFBundleName + axs + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSApplicationQueriesSchemes + + tg + weixin + wechat + googlegmail + x-dispatch + readdle-spark + airmail + ms-outlook + ymail + fastmail + superhuman + protonmail + + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + No + NSAppTransportSecurity + + NSAllowsArbitraryLoads + NSAppleMusicUsageDescription + Would you allow AXS Wallet to use the Media Library? + NSBluetoothPeripheralUsageDescription + Would you allow AXS Wallet to use the Bluetooth? + NSCalendarsUsageDescription + Would you allow AXS Wallet to use the Calendar? + NSCameraUsageDescription + AXS Wallet needs access to your camera when the app is in use for services such as RWA minting. Image data is not saved or shared with any third parties. + NSFaceIDUsageDescription + AXS Wallet needs access to your Biometric data when the app is in use for authentication only. Your Biometric data is not saved or shared with any third parties. + NSLocationAlwaysAndWhenInUseUsageDescription + AXS Wallet needs access to your location for features such as Wi-Fi hooks while the app is in use or running in the background. Your location data is not saved or shared with any third parties. + NSLocationAlwaysUsageDescription + AXS Wallet requires access to your location at all times for services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. + NSLocationUsageDescription + AXS Wallet needs access to your location to provide services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. + NSLocationWhenInUseUsageDescription + AXS Wallet needs access to your location when the app is in use for services such as Wi-Fi hooks. Your location data is not saved or shared with any third parties. + NSMotionUsageDescription + Would you allow AXS Wallet to use the Motion? + NSPhotoLibraryAddUsageDescription + AXS Wallet needs access to your photos to save images such as RWA. Your photos are not saved or shared with any third parties. + NSPhotoLibraryUsageDescription + AXS Wallet needs access to your photos when the app is in use for services such as RWA minting. Your photos are not saved or shared with any third parties. + NSSpeechRecognitionUsageDescription + Would you allow AXS Wallet to use the Speech Recognition? + PermissionGroupNotification + Would you allow AXS Wallet to use the Notification? + NSBluetoothAlwaysUsageDescription + AXS Wallet needs access to your Bluetooth when the app is in use or running in the background for services such as BluberryRing. Blutooth data is not saved or shared with any third parties. + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + location + processing + remote-notification + bluetooth-central + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + UISupportsDocumentBrowser + + From 36e05ca71ba753827205839993d4e65b823cd23c Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 24 Jul 2024 11:26:50 +0330 Subject: [PATCH 10/45] feat: Add blueberry ring contracts --- .../ens_dart/lib/src/contracts/contracts.dart | 1 + .../contracts/doit/BlueberryRingNFT.g.dart | 975 ++++++++++++++++++ .../src/contracts/doit/DoitRINGDevice.g.dart | 630 +++++++++++ .../src/contracts/doit/DoitRINGFriend.g.dart | 935 +++++++++++++++++ .../src/contracts/doit/DoitRINGStake.g.dart | 613 +++++++++++ .../ens_dart/lib/src/contracts/doit/doit.dart | 4 + .../lib/src/json/BlueberryRingNFT.abi.json | 773 ++++++++++++++ .../lib/src/json/DoitRINGDevice.abi.json | 695 +++++++++++++ .../lib/src/json/DoitRINGFriend.abi.json | 846 +++++++++++++++ .../lib/src/json/DoitRINGStake.abi.json | 606 +++++++++++ packages/shared | 2 +- 11 files changed, 6079 insertions(+), 1 deletion(-) create mode 100644 packages/ens_dart/lib/src/contracts/doit/BlueberryRingNFT.g.dart create mode 100644 packages/ens_dart/lib/src/contracts/doit/DoitRINGDevice.g.dart create mode 100644 packages/ens_dart/lib/src/contracts/doit/DoitRINGFriend.g.dart create mode 100644 packages/ens_dart/lib/src/contracts/doit/DoitRINGStake.g.dart create mode 100644 packages/ens_dart/lib/src/contracts/doit/doit.dart create mode 100644 packages/ens_dart/lib/src/json/BlueberryRingNFT.abi.json create mode 100644 packages/ens_dart/lib/src/json/DoitRINGDevice.abi.json create mode 100644 packages/ens_dart/lib/src/json/DoitRINGFriend.abi.json create mode 100644 packages/ens_dart/lib/src/json/DoitRINGStake.abi.json diff --git a/packages/ens_dart/lib/src/contracts/contracts.dart b/packages/ens_dart/lib/src/contracts/contracts.dart index f0431d7e..c4cdcbe5 100644 --- a/packages/ens_dart/lib/src/contracts/contracts.dart +++ b/packages/ens_dart/lib/src/contracts/contracts.dart @@ -13,3 +13,4 @@ export 'erc_6551_account_impl.g.dart'; export 'mep2542.g.dart' hide Initialized, OwnershipTransferred, ControllerChanged; export 'erc_6551_registry.g.dart'; +export 'doit/doit.dart'; \ No newline at end of file diff --git a/packages/ens_dart/lib/src/contracts/doit/BlueberryRingNFT.g.dart b/packages/ens_dart/lib/src/contracts/doit/BlueberryRingNFT.g.dart new file mode 100644 index 00000000..74223b11 --- /dev/null +++ b/packages/ens_dart/lib/src/contracts/doit/BlueberryRingNFT.g.dart @@ -0,0 +1,975 @@ +// Generated code, do not modify. Run `build_runner build` to re-generate! +// @dart=2.12 +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:web3dart/web3dart.dart' as _i1; +import 'dart:typed_data' as _i2; + +final _contractAbi = _i1.ContractAbi.fromJson( + '[{"inputs":[],"name":"MXCCollection__BurnMintError","type":"error"},{"inputs":[],"name":"MXCCollection__NotAuthorize","type":"error"},{"inputs":[],"name":"MXCCollection__NotCreator","type":"error"},{"inputs":[],"name":"MXCCollection__NotExistToken","type":"error"},{"inputs":[],"name":"MXCCollection__NotOwner","type":"error"},{"inputs":[],"name":"MXCCollection__StakedTokenTransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nft","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnMXC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"burnMXCMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"existSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBurnMXC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"},{"internalType":"address","name":"owner","type":"address"}],"name":"gift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"address","name":"_royaltyRecipient","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_royaltiesCutPerMillion","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"initializeERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"},{"internalType":"uint256","name":"stakedAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltiesCutPerMillion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"uint256","name":"royaltyAmount","type":"uint256"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyRecipientAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setBurnMXC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nft","type":"uint256"}],"name":"stakedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]', + 'BlueberryRingNFT', +); + +class BlueberryRingNFT extends _i1.GeneratedContract { + BlueberryRingNFT({ + required _i1.EthereumAddress address, + required _i1.Web3Client client, + int? chainId, + }) : super( + _i1.DeployedContract( + _contractAbi, + address, + ), + client, + chainId, + ); + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future approve( + _i1.EthereumAddress spender, + BigInt id, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[0]; + assert(checkSignature(function, '095ea7b3')); + final params = [ + spender, + id, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future balanceOf( + _i1.EthereumAddress owner, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[1]; + assert(checkSignature(function, '70a08231')); + final params = [owner]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future burn( + BigInt nft, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[2]; + assert(checkSignature(function, '42966c68')); + final params = [nft]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future burnMXC({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[3]; + assert(checkSignature(function, '5492ed1c')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future burnMXCMint( + String _tokenURI, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[4]; + assert(checkSignature(function, '07cd5d9e')); + final params = [_tokenURI]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> collateral({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[5]; + assert(checkSignature(function, 'd8dfeb45')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> creator({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[6]; + assert(checkSignature(function, '02d05d3f')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future existSupply({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[7]; + assert(checkSignature(function, '486f6c3e')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> getApproved( + BigInt $param5, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[8]; + assert(checkSignature(function, '081812fc')); + final params = [$param5]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getBurnMXC({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[9]; + assert(checkSignature(function, '0bfda73b')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getVersion({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[10]; + assert(checkSignature(function, '0d8e6e2c')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future gift( + String _tokenURI, + _i1.EthereumAddress owner, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[11]; + assert(checkSignature(function, '415665d5')); + final params = [ + _tokenURI, + owner, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future initialize( + _i1.EthereumAddress _creator, + _i1.EthereumAddress _royaltyRecipient, + _i1.EthereumAddress _collateral, + BigInt _royaltiesCutPerMillion, + String _name, + String _symbol, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[12]; + assert(checkSignature(function, '5cf3ad31')); + final params = [ + _creator, + _royaltyRecipient, + _collateral, + _royaltiesCutPerMillion, + _name, + _symbol, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future initializeERC721( + String _name, + String _symbol, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[13]; + assert(checkSignature(function, 'd147c97a')); + final params = [ + _name, + _symbol, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future isApprovedForAll( + _i1.EthereumAddress $param16, + _i1.EthereumAddress $param17, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[14]; + assert(checkSignature(function, 'e985e9c5')); + final params = [ + $param16, + $param17, + ]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future mint( + String _tokenURI, + BigInt stakedAmount, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[15]; + assert(checkSignature(function, '056b01ce')); + final params = [ + _tokenURI, + stakedAmount, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future name({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[16]; + assert(checkSignature(function, '06fdde03')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> ownerOf( + BigInt id, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[17]; + assert(checkSignature(function, '6352211e')); + final params = [id]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i2.Uint8List> proxiableUUID({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[18]; + assert(checkSignature(function, '52d1902d')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i2.Uint8List); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future royaltiesCutPerMillion({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[19]; + assert(checkSignature(function, 'ce2243b4')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future royaltyInfo( + BigInt _salePrice, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[20]; + assert(checkSignature(function, 'cef6d368')); + final params = [_salePrice]; + final response = await read( + function, + params, + atBlock, + ); + return RoyaltyInfo(response); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> royaltyRecipientAddress( + {_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[21]; + assert(checkSignature(function, '343def02')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future safeTransferFrom( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt id, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[22]; + assert(checkSignature(function, '42842e0e')); + final params = [ + from, + to, + id, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future safeTransferFrom$2( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt id, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[23]; + assert(checkSignature(function, 'b88d4fde')); + final params = [ + from, + to, + id, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future setApprovalForAll( + _i1.EthereumAddress operator, + bool approved, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[24]; + assert(checkSignature(function, 'a22cb465')); + final params = [ + operator, + approved, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future setBurnMXC( + BigInt amount, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[25]; + assert(checkSignature(function, 'f6f315ac')); + final params = [amount]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future setTokenURI( + BigInt tokenId, + String uri, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[26]; + assert(checkSignature(function, '162094c4')); + final params = [ + tokenId, + uri, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future stakedBalanceOf( + BigInt nft, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[27]; + assert(checkSignature(function, 'aa04295f')); + final params = [nft]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future supportsInterface( + _i2.Uint8List interfaceId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[28]; + assert(checkSignature(function, '01ffc9a7')); + final params = [interfaceId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future symbol({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[29]; + assert(checkSignature(function, '95d89b41')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future tokenURI( + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[30]; + assert(checkSignature(function, 'c87b56dd')); + final params = [tokenId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future totalSupply({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[31]; + assert(checkSignature(function, '18160ddd')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferFrom( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt id, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[32]; + assert(checkSignature(function, '23b872dd')); + final params = [ + from, + to, + id, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future upgradeTo( + _i1.EthereumAddress newImplementation, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[33]; + assert(checkSignature(function, '3659cfe6')); + final params = [newImplementation]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future upgradeToAndCall( + _i1.EthereumAddress newImplementation, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[34]; + assert(checkSignature(function, '4f1ef286')); + final params = [ + newImplementation, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// Returns a live stream of all AdminChanged events emitted by this contract. + Stream adminChangedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('AdminChanged'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return AdminChanged( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Approval events emitted by this contract. + Stream approvalEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Approval'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Approval( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all ApprovalForAll events emitted by this contract. + Stream approvalForAllEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('ApprovalForAll'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return ApprovalForAll( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all BeaconUpgraded events emitted by this contract. + Stream beaconUpgradedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('BeaconUpgraded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return BeaconUpgraded( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Initialized events emitted by this contract. + Stream initializedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Initialized'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Initialized( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Transfer events emitted by this contract. + Stream transferEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Transfer'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Transfer( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Upgraded events emitted by this contract. + Stream upgradedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Upgraded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Upgraded( + decoded, + result, + ); + }); + } +} + +class RoyaltyInfo { + RoyaltyInfo(List response) + : royaltyAmount = (response[0] as BigInt), + royaltyRecipient = (response[1] as _i1.EthereumAddress); + + final BigInt royaltyAmount; + + final _i1.EthereumAddress royaltyRecipient; +} + +class AdminChanged { + AdminChanged( + List response, + this.event, + ) : previousAdmin = (response[0] as _i1.EthereumAddress), + newAdmin = (response[1] as _i1.EthereumAddress); + + final _i1.EthereumAddress previousAdmin; + + final _i1.EthereumAddress newAdmin; + + final _i1.FilterEvent event; +} + +class Approval { + Approval( + List response, + this.event, + ) : owner = (response[0] as _i1.EthereumAddress), + spender = (response[1] as _i1.EthereumAddress), + id = (response[2] as BigInt); + + final _i1.EthereumAddress owner; + + final _i1.EthereumAddress spender; + + final BigInt id; + + final _i1.FilterEvent event; +} + +class ApprovalForAll { + ApprovalForAll( + List response, + this.event, + ) : owner = (response[0] as _i1.EthereumAddress), + operator = (response[1] as _i1.EthereumAddress), + approved = (response[2] as bool); + + final _i1.EthereumAddress owner; + + final _i1.EthereumAddress operator; + + final bool approved; + + final _i1.FilterEvent event; +} + +class BeaconUpgraded { + BeaconUpgraded( + List response, + this.event, + ) : beacon = (response[0] as _i1.EthereumAddress); + + final _i1.EthereumAddress beacon; + + final _i1.FilterEvent event; +} + +class Initialized { + Initialized( + List response, + this.event, + ) : version = (response[0] as BigInt); + + final BigInt version; + + final _i1.FilterEvent event; +} + +class Transfer { + Transfer( + List response, + this.event, + ) : from = (response[0] as _i1.EthereumAddress), + to = (response[1] as _i1.EthereumAddress), + id = (response[2] as BigInt); + + final _i1.EthereumAddress from; + + final _i1.EthereumAddress to; + + final BigInt id; + + final _i1.FilterEvent event; +} + +class Upgraded { + Upgraded( + List response, + this.event, + ) : implementation = (response[0] as _i1.EthereumAddress); + + final _i1.EthereumAddress implementation; + + final _i1.FilterEvent event; +} diff --git a/packages/ens_dart/lib/src/contracts/doit/DoitRINGDevice.g.dart b/packages/ens_dart/lib/src/contracts/doit/DoitRINGDevice.g.dart new file mode 100644 index 00000000..1af7b957 --- /dev/null +++ b/packages/ens_dart/lib/src/contracts/doit/DoitRINGDevice.g.dart @@ -0,0 +1,630 @@ +// Generated code, do not modify. Run `build_runner build` to re-generate! +// @dart=2.12 +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:web3dart/web3dart.dart' as _i1; +import 'dart:typed_data' as _i2; + +final _contractAbi = _i1.ContractAbi.fromJson( + '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"ClaimInvalidClaimed","type":"error"},{"inputs":[],"name":"DeviceEmpty","type":"error"},{"inputs":[],"name":"DeviceRegistered","type":"error"},{"inputs":[],"name":"DeviceUnregistered","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferUnauthorized","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"string","name":"sncode","type":"string"}],"name":"Binded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"sncode","type":"string"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct DoitRINGDevice.Reward[]","name":"rewards","type":"tuple[]"},{"indexed":false,"internalType":"string","name":"memo","type":"string"},{"indexed":false,"internalType":"int256","name":"blockHeight","type":"int256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"string","name":"sncode","type":"string"},{"indexed":false,"internalType":"int256","name":"blockHeight","type":"int256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"uid","type":"string"},{"internalType":"string","name":"sncode","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct DoitRINGDevice.Reward[]","name":"rewards","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"string","name":"memo","type":"string"}],"name":"claimInOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uid","type":"string"},{"internalType":"string","name":"sncode","type":"string"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct DoitRINGDevice.Reward[]","name":"rewards","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"string","name":"memo","type":"string"}],"name":"claimInSender","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"existsBinded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getDeviceInAddress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getDeviceInToken","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"int256","name":"height","type":"int256"},{"internalType":"string","name":"sncode","type":"string"}],"internalType":"struct DoitRINGDevice.DeviceMapping","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getTokenInAddress","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct DoitRINGDevice.TokenMapping","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"sncode","type":"string"}],"name":"getTokenInDevice","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct DoitRINGDevice.TokenMapping","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_verifier","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"sncode","type":"string"}],"name":"rebind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"sncode","type":"string"}],"name":"registerInSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]', + 'DoitRINGDevice', +); + +class DoitRINGDevice extends _i1.GeneratedContract { + DoitRINGDevice({ + required _i1.EthereumAddress address, + required _i1.Web3Client client, + int? chainId, + }) : super( + _i1.DeployedContract( + _contractAbi, + address, + ), + client, + chainId, + ); + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future UPGRADE_INTERFACE_VERSION({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[1]; + assert(checkSignature(function, 'ad3cb1cc')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future claimInOwner( + String uid, + String sncode, + _i1.EthereumAddress owner, + List rewards, + _i2.Uint8List signature, + String memo, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[2]; + assert(checkSignature(function, 'da3d17ac')); + final params = [ + uid, + sncode, + owner, + rewards, + signature, + memo, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future claimInSender( + String uid, + String sncode, + List rewards, + _i2.Uint8List signature, + String memo, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[3]; + assert(checkSignature(function, 'd1acb504')); + final params = [ + uid, + sncode, + rewards, + signature, + memo, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future existsBinded( + _i1.EthereumAddress token, + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[4]; + assert(checkSignature(function, 'cf28e52c')); + final params = [ + token, + tokenId, + ]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getDeviceInAddress( + _i1.EthereumAddress user, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[5]; + assert(checkSignature(function, '74781d7e')); + final params = [user]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getDeviceInToken( + _i1.EthereumAddress token, + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[6]; + assert(checkSignature(function, '97826852')); + final params = [ + token, + tokenId, + ]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as dynamic); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getTokenInAddress( + _i1.EthereumAddress user, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[7]; + assert(checkSignature(function, 'a65d864e')); + final params = [user]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as dynamic); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future getTokenInDevice( + String sncode, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[8]; + assert(checkSignature(function, '8125f9e4')); + final params = [sncode]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as dynamic); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future initialize( + _i1.EthereumAddress _owner, + _i1.EthereumAddress _verifier, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[9]; + assert(checkSignature(function, '485cc955')); + final params = [ + _owner, + _verifier, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> owner({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[10]; + assert(checkSignature(function, '8da5cb5b')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i2.Uint8List> proxiableUUID({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[11]; + assert(checkSignature(function, '52d1902d')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i2.Uint8List); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future rebind( + String sncode, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[12]; + assert(checkSignature(function, 'f9c9b22f')); + final params = [sncode]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future registerInSender( + _i1.EthereumAddress token, + BigInt tokenId, + String sncode, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[13]; + assert(checkSignature(function, '2e2dc127')); + final params = [ + token, + tokenId, + sncode, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future renounceOwnership({ + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[14]; + assert(checkSignature(function, '715018a6')); + final params = []; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferOwnership( + _i1.EthereumAddress newOwner, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[15]; + assert(checkSignature(function, 'f2fde38b')); + final params = [newOwner]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future upgradeToAndCall( + _i1.EthereumAddress newImplementation, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[16]; + assert(checkSignature(function, '4f1ef286')); + final params = [ + newImplementation, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future withdraw( + _i1.EthereumAddress token, + BigInt amount, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[17]; + assert(checkSignature(function, 'f3fef3a3')); + final params = [ + token, + amount, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// Returns a live stream of all Binded events emitted by this contract. + Stream bindedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Binded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Binded( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Claimed events emitted by this contract. + Stream claimedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Claimed'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Claimed( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Initialized events emitted by this contract. + Stream initializedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Initialized'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Initialized( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all OwnershipTransferred events emitted by this contract. + Stream ownershipTransferredEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('OwnershipTransferred'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return OwnershipTransferred( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Registered events emitted by this contract. + Stream registeredEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Registered'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Registered( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Upgraded events emitted by this contract. + Stream upgradedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Upgraded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Upgraded( + decoded, + result, + ); + }); + } +} + +class Binded { + Binded( + List response, + this.event, + ) : owner = (response[0] as _i1.EthereumAddress), + sncode = (response[1] as String); + + final _i1.EthereumAddress owner; + + final String sncode; + + final _i1.FilterEvent event; +} + +class Claimed { + Claimed( + List response, + this.event, + ) : sncode = (response[0] as String), + token = (response[1] as _i1.EthereumAddress), + tokenId = (response[2] as BigInt), + to = (response[3] as _i1.EthereumAddress), + rewards = (response[4] as List).cast(), + memo = (response[5] as String), + blockHeight = (response[6] as BigInt), + timestamp = (response[7] as BigInt); + + final String sncode; + + final _i1.EthereumAddress token; + + final BigInt tokenId; + + final _i1.EthereumAddress to; + + final List rewards; + + final String memo; + + final BigInt blockHeight; + + final BigInt timestamp; + + final _i1.FilterEvent event; +} + +class Initialized { + Initialized( + List response, + this.event, + ) : version = (response[0] as BigInt); + + final BigInt version; + + final _i1.FilterEvent event; +} + +class OwnershipTransferred { + OwnershipTransferred( + List response, + this.event, + ) : previousOwner = (response[0] as _i1.EthereumAddress), + newOwner = (response[1] as _i1.EthereumAddress); + + final _i1.EthereumAddress previousOwner; + + final _i1.EthereumAddress newOwner; + + final _i1.FilterEvent event; +} + +class Registered { + Registered( + List response, + this.event, + ) : token = (response[0] as _i1.EthereumAddress), + tokenId = (response[1] as BigInt), + sender = (response[2] as _i1.EthereumAddress), + sncode = (response[3] as String), + blockHeight = (response[4] as BigInt), + timestamp = (response[5] as BigInt); + + final _i1.EthereumAddress token; + + final BigInt tokenId; + + final _i1.EthereumAddress sender; + + final String sncode; + + final BigInt blockHeight; + + final BigInt timestamp; + + final _i1.FilterEvent event; +} + +class Upgraded { + Upgraded( + List response, + this.event, + ) : implementation = (response[0] as _i1.EthereumAddress); + + final _i1.EthereumAddress implementation; + + final _i1.FilterEvent event; +} diff --git a/packages/ens_dart/lib/src/contracts/doit/DoitRINGFriend.g.dart b/packages/ens_dart/lib/src/contracts/doit/DoitRINGFriend.g.dart new file mode 100644 index 00000000..d29a116e --- /dev/null +++ b/packages/ens_dart/lib/src/contracts/doit/DoitRINGFriend.g.dart @@ -0,0 +1,935 @@ +// Generated code, do not modify. Run `build_runner build` to re-generate! +// @dart=2.12 +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:web3dart/web3dart.dart' as _i1; +import 'dart:typed_data' as _i2; + +final _contractAbi = _i1.ContractAbi.fromJson( + '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[],"name":"UserAlreadyInGroup","type":"error"},{"inputs":[],"name":"UserNotInGroup","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"group","type":"uint256"},{"indexed":false,"internalType":"string","name":"tokenURI","type":"string"}],"name":"GroupCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"group","type":"uint256"}],"name":"GroupJoined","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"group","type":"uint256"}],"name":"GroupLeft","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"group","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_verifier","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"join","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"leave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userToGroup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]', + 'DoitRINGFriend', +); + +class DoitRINGFriend extends _i1.GeneratedContract { + DoitRINGFriend({ + required _i1.EthereumAddress address, + required _i1.Web3Client client, + int? chainId, + }) : super( + _i1.DeployedContract( + _contractAbi, + address, + ), + client, + chainId, + ); + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future UPGRADE_INTERFACE_VERSION({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[1]; + assert(checkSignature(function, 'ad3cb1cc')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future approve( + _i1.EthereumAddress to, + BigInt tokenId, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[2]; + assert(checkSignature(function, '095ea7b3')); + final params = [ + to, + tokenId, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future balanceOf( + _i1.EthereumAddress owner, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[3]; + assert(checkSignature(function, '70a08231')); + final params = [owner]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future create( + String tokenURI, + _i2.Uint8List signature, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[4]; + assert(checkSignature(function, 'bcebbe80')); + final params = [ + tokenURI, + signature, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> getApproved( + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[5]; + assert(checkSignature(function, '081812fc')); + final params = [tokenId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future group( + _i1.EthereumAddress user, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[6]; + assert(checkSignature(function, '7b5cf44f')); + final params = [user]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future initialize( + _i1.EthereumAddress _owner, + _i1.EthereumAddress _verifier, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[7]; + assert(checkSignature(function, '485cc955')); + final params = [ + _owner, + _verifier, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future isApprovedForAll( + _i1.EthereumAddress owner, + _i1.EthereumAddress operator, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[8]; + assert(checkSignature(function, 'e985e9c5')); + final params = [ + owner, + operator, + ]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future join( + BigInt groupId, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[9]; + assert(checkSignature(function, '049878f3')); + final params = [groupId]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future leave({ + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[10]; + assert(checkSignature(function, 'd66d9e19')); + final params = []; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future name({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[11]; + assert(checkSignature(function, '06fdde03')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> owner({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[12]; + assert(checkSignature(function, '8da5cb5b')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> ownerOf( + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[13]; + assert(checkSignature(function, '6352211e')); + final params = [tokenId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i2.Uint8List> proxiableUUID({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[14]; + assert(checkSignature(function, '52d1902d')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i2.Uint8List); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future renounceOwnership({ + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[15]; + assert(checkSignature(function, '715018a6')); + final params = []; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future safeTransferFrom( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt tokenId, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[16]; + assert(checkSignature(function, '42842e0e')); + final params = [ + from, + to, + tokenId, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future safeTransferFrom$2( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt tokenId, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[17]; + assert(checkSignature(function, 'b88d4fde')); + final params = [ + from, + to, + tokenId, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future setApprovalForAll( + _i1.EthereumAddress operator, + bool approved, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[18]; + assert(checkSignature(function, 'a22cb465')); + final params = [ + operator, + approved, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future supportsInterface( + _i2.Uint8List interfaceId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[19]; + assert(checkSignature(function, '01ffc9a7')); + final params = [interfaceId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future symbol({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[20]; + assert(checkSignature(function, '95d89b41')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future tokenURI( + BigInt tokenId, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[21]; + assert(checkSignature(function, 'c87b56dd')); + final params = [tokenId]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferFrom( + _i1.EthereumAddress from, + _i1.EthereumAddress to, + BigInt tokenId, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[22]; + assert(checkSignature(function, '23b872dd')); + final params = [ + from, + to, + tokenId, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferOwnership( + _i1.EthereumAddress newOwner, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[23]; + assert(checkSignature(function, 'f2fde38b')); + final params = [newOwner]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future upgradeToAndCall( + _i1.EthereumAddress newImplementation, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[24]; + assert(checkSignature(function, '4f1ef286')); + final params = [ + newImplementation, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future userToGroup( + _i1.EthereumAddress $param30, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[25]; + assert(checkSignature(function, 'f3b90296')); + final params = [$param30]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// Returns a live stream of all Approval events emitted by this contract. + Stream approvalEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Approval'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Approval( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all ApprovalForAll events emitted by this contract. + Stream approvalForAllEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('ApprovalForAll'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return ApprovalForAll( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all BatchMetadataUpdate events emitted by this contract. + Stream batchMetadataUpdateEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('BatchMetadataUpdate'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return BatchMetadataUpdate( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all GroupCreated events emitted by this contract. + Stream groupCreatedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('GroupCreated'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return GroupCreated( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all GroupJoined events emitted by this contract. + Stream groupJoinedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('GroupJoined'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return GroupJoined( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all GroupLeft events emitted by this contract. + Stream groupLeftEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('GroupLeft'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return GroupLeft( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Initialized events emitted by this contract. + Stream initializedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Initialized'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Initialized( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all MetadataUpdate events emitted by this contract. + Stream metadataUpdateEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('MetadataUpdate'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return MetadataUpdate( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all OwnershipTransferred events emitted by this contract. + Stream ownershipTransferredEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('OwnershipTransferred'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return OwnershipTransferred( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Transfer events emitted by this contract. + Stream transferEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Transfer'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Transfer( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Upgraded events emitted by this contract. + Stream upgradedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Upgraded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Upgraded( + decoded, + result, + ); + }); + } +} + +class Approval { + Approval( + List response, + this.event, + ) : owner = (response[0] as _i1.EthereumAddress), + approved = (response[1] as _i1.EthereumAddress), + tokenId = (response[2] as BigInt); + + final _i1.EthereumAddress owner; + + final _i1.EthereumAddress approved; + + final BigInt tokenId; + + final _i1.FilterEvent event; +} + +class ApprovalForAll { + ApprovalForAll( + List response, + this.event, + ) : owner = (response[0] as _i1.EthereumAddress), + operator = (response[1] as _i1.EthereumAddress), + approved = (response[2] as bool); + + final _i1.EthereumAddress owner; + + final _i1.EthereumAddress operator; + + final bool approved; + + final _i1.FilterEvent event; +} + +class BatchMetadataUpdate { + BatchMetadataUpdate( + List response, + this.event, + ) : fromTokenId = (response[0] as BigInt), + toTokenId = (response[1] as BigInt); + + final BigInt fromTokenId; + + final BigInt toTokenId; + + final _i1.FilterEvent event; +} + +class GroupCreated { + GroupCreated( + List response, + this.event, + ) : creator = (response[0] as _i1.EthereumAddress), + group = (response[1] as BigInt), + tokenURI = (response[2] as String); + + final _i1.EthereumAddress creator; + + final BigInt group; + + final String tokenURI; + + final _i1.FilterEvent event; +} + +class GroupJoined { + GroupJoined( + List response, + this.event, + ) : user = (response[0] as _i1.EthereumAddress), + group = (response[1] as BigInt); + + final _i1.EthereumAddress user; + + final BigInt group; + + final _i1.FilterEvent event; +} + +class GroupLeft { + GroupLeft( + List response, + this.event, + ) : user = (response[0] as _i1.EthereumAddress), + group = (response[1] as BigInt); + + final _i1.EthereumAddress user; + + final BigInt group; + + final _i1.FilterEvent event; +} + +class Initialized { + Initialized( + List response, + this.event, + ) : version = (response[0] as BigInt); + + final BigInt version; + + final _i1.FilterEvent event; +} + +class MetadataUpdate { + MetadataUpdate( + List response, + this.event, + ) : tokenId = (response[0] as BigInt); + + final BigInt tokenId; + + final _i1.FilterEvent event; +} + +class OwnershipTransferred { + OwnershipTransferred( + List response, + this.event, + ) : previousOwner = (response[0] as _i1.EthereumAddress), + newOwner = (response[1] as _i1.EthereumAddress); + + final _i1.EthereumAddress previousOwner; + + final _i1.EthereumAddress newOwner; + + final _i1.FilterEvent event; +} + +class Transfer { + Transfer( + List response, + this.event, + ) : from = (response[0] as _i1.EthereumAddress), + to = (response[1] as _i1.EthereumAddress), + tokenId = (response[2] as BigInt); + + final _i1.EthereumAddress from; + + final _i1.EthereumAddress to; + + final BigInt tokenId; + + final _i1.FilterEvent event; +} + +class Upgraded { + Upgraded( + List response, + this.event, + ) : implementation = (response[0] as _i1.EthereumAddress); + + final _i1.EthereumAddress implementation; + + final _i1.FilterEvent event; +} diff --git a/packages/ens_dart/lib/src/contracts/doit/DoitRINGStake.g.dart b/packages/ens_dart/lib/src/contracts/doit/DoitRINGStake.g.dart new file mode 100644 index 00000000..6780aaac --- /dev/null +++ b/packages/ens_dart/lib/src/contracts/doit/DoitRINGStake.g.dart @@ -0,0 +1,613 @@ +// Generated code, do not modify. Run `build_runner build` to re-generate! +// @dart=2.12 +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:web3dart/web3dart.dart' as _i1; +import 'dart:typed_data' as _i2; + +final _contractAbi = _i1.ContractAbi.fromJson( + '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"StakeAmountEmpty","type":"error"},{"inputs":[],"name":"StakeCancelEmpty","type":"error"},{"inputs":[],"name":"StakeCancelUnexpired","type":"error"},{"inputs":[],"name":"StakeEmpty","type":"error"},{"inputs":[],"name":"TokenTransferFailed","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferUnauthorized","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StakeCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StakeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StakeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"Cancells","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"Stakes","outputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"index","type":"uint128"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"index","type":"uint128"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"index","type":"uint128"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"index","type":"uint128"}],"name":"expiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"length","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"stakes","outputs":[{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IStake.Stake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"index","type":"uint128"}],"name":"status","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]', + 'DoitRINGStake', +); + +class DoitRINGStake extends _i1.GeneratedContract { + DoitRINGStake({ + required _i1.EthereumAddress address, + required _i1.Web3Client client, + int? chainId, + }) : super( + _i1.DeployedContract( + _contractAbi, + address, + ), + client, + chainId, + ); + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future Cancells( + _i1.EthereumAddress $param0, + BigInt $param1, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[1]; + assert(checkSignature(function, 'a7ff9d0f')); + final params = [ + $param0, + $param1, + ]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The real function name is Stakes + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future stakesWithBigS( + _i1.EthereumAddress $param2, + BigInt $param3, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[2]; + assert(checkSignature(function, '35de3234')); + final params = [ + $param2, + $param3, + ]; + final response = await read( + function, + params, + atBlock, + ); + return Stakes(response); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future UPGRADE_INTERFACE_VERSION({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[3]; + assert(checkSignature(function, 'ad3cb1cc')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as String); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future cancel( + BigInt index, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[4]; + assert(checkSignature(function, '81649d06')); + final params = [index]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future claim( + BigInt index, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[5]; + assert(checkSignature(function, '60e72adb')); + final params = [index]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future create( + _i1.EthereumAddress token, + BigInt amount, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[6]; + assert(checkSignature(function, '0ecaea73')); + final params = [ + token, + amount, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future exists( + BigInt index, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[7]; + assert(checkSignature(function, 'cae2f0d9')); + final params = [index]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as bool); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future expiration( + BigInt index, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[8]; + assert(checkSignature(function, '59cdb318')); + final params = [index]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future initialize( + _i1.EthereumAddress _owner, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[9]; + assert(checkSignature(function, 'c4d66de8')); + final params = [_owner]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future length( + _i1.EthereumAddress owner, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[10]; + assert(checkSignature(function, '2c566ae5')); + final params = [owner]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i1.EthereumAddress> owner({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[11]; + assert(checkSignature(function, '8da5cb5b')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i1.EthereumAddress); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future<_i2.Uint8List> proxiableUUID({_i1.BlockNum? atBlock}) async { + final function = self.abi.functions[12]; + assert(checkSignature(function, '52d1902d')); + final params = []; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as _i2.Uint8List); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future renounceOwnership({ + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[13]; + assert(checkSignature(function, '715018a6')); + final params = []; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future> stakes( + _i1.EthereumAddress owner, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[14]; + assert(checkSignature(function, '16934fc4')); + final params = [owner]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as List).cast(); + } + + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future status( + BigInt index, { + _i1.BlockNum? atBlock, + }) async { + final function = self.abi.functions[15]; + assert(checkSignature(function, 'f596e6e1')); + final params = [index]; + final response = await read( + function, + params, + atBlock, + ); + return (response[0] as BigInt); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferOwnership( + _i1.EthereumAddress newOwner, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[16]; + assert(checkSignature(function, 'f2fde38b')); + final params = [newOwner]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future upgradeToAndCall( + _i1.EthereumAddress newImplementation, + _i2.Uint8List data, { + required _i1.Credentials credentials, + _i1.Transaction? transaction, + }) async { + final function = self.abi.functions[17]; + assert(checkSignature(function, '4f1ef286')); + final params = [ + newImplementation, + data, + ]; + return write( + credentials, + transaction, + function, + params, + ); + } + + /// Returns a live stream of all Initialized events emitted by this contract. + Stream initializedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Initialized'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Initialized( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all OwnershipTransferred events emitted by this contract. + Stream ownershipTransferredEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('OwnershipTransferred'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return OwnershipTransferred( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all StakeCancelled events emitted by this contract. + Stream stakeCancelledEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('StakeCancelled'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return StakeCancelled( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all StakeClaimed events emitted by this contract. + Stream stakeClaimedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('StakeClaimed'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return StakeClaimed( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all StakeCreated events emitted by this contract. + Stream stakeCreatedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('StakeCreated'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return StakeCreated( + decoded, + result, + ); + }); + } + + /// Returns a live stream of all Upgraded events emitted by this contract. + Stream upgradedEvents({ + _i1.BlockNum? fromBlock, + _i1.BlockNum? toBlock, + }) { + final event = self.event('Upgraded'); + final filter = _i1.FilterOptions.events( + contract: self, + event: event, + fromBlock: fromBlock, + toBlock: toBlock, + ); + return client.events(filter).map((_i1.FilterEvent result) { + final decoded = event.decodeResults( + result.topics!, + result.data!, + ); + return Upgraded( + decoded, + result, + ); + }); + } +} + +class Stakes { + Stakes(List response) + : index = (response[0] as BigInt), + staker = (response[1] as _i1.EthereumAddress), + token = (response[2] as _i1.EthereumAddress), + amount = (response[3] as BigInt), + timestamp = (response[4] as BigInt); + + final BigInt index; + + final _i1.EthereumAddress staker; + + final _i1.EthereumAddress token; + + final BigInt amount; + + final BigInt timestamp; +} + +class Initialized { + Initialized( + List response, + this.event, + ) : version = (response[0] as BigInt); + + final BigInt version; + + final _i1.FilterEvent event; +} + +class OwnershipTransferred { + OwnershipTransferred( + List response, + this.event, + ) : previousOwner = (response[0] as _i1.EthereumAddress), + newOwner = (response[1] as _i1.EthereumAddress); + + final _i1.EthereumAddress previousOwner; + + final _i1.EthereumAddress newOwner; + + final _i1.FilterEvent event; +} + +class StakeCancelled { + StakeCancelled( + List response, + this.event, + ) : staker = (response[0] as _i1.EthereumAddress), + index = (response[1] as BigInt), + token = (response[2] as _i1.EthereumAddress), + amount = (response[3] as BigInt), + timestamp = (response[4] as BigInt); + + final _i1.EthereumAddress staker; + + final BigInt index; + + final _i1.EthereumAddress token; + + final BigInt amount; + + final BigInt timestamp; + + final _i1.FilterEvent event; +} + +class StakeClaimed { + StakeClaimed( + List response, + this.event, + ) : staker = (response[0] as _i1.EthereumAddress), + index = (response[1] as BigInt), + token = (response[2] as _i1.EthereumAddress), + amount = (response[3] as BigInt), + timestamp = (response[4] as BigInt); + + final _i1.EthereumAddress staker; + + final BigInt index; + + final _i1.EthereumAddress token; + + final BigInt amount; + + final BigInt timestamp; + + final _i1.FilterEvent event; +} + +class StakeCreated { + StakeCreated( + List response, + this.event, + ) : staker = (response[0] as _i1.EthereumAddress), + index = (response[1] as BigInt), + token = (response[2] as _i1.EthereumAddress), + amount = (response[3] as BigInt), + timestamp = (response[4] as BigInt); + + final _i1.EthereumAddress staker; + + final BigInt index; + + final _i1.EthereumAddress token; + + final BigInt amount; + + final BigInt timestamp; + + final _i1.FilterEvent event; +} + +class Upgraded { + Upgraded( + List response, + this.event, + ) : implementation = (response[0] as _i1.EthereumAddress); + + final _i1.EthereumAddress implementation; + + final _i1.FilterEvent event; +} diff --git a/packages/ens_dart/lib/src/contracts/doit/doit.dart b/packages/ens_dart/lib/src/contracts/doit/doit.dart new file mode 100644 index 00000000..5146369d --- /dev/null +++ b/packages/ens_dart/lib/src/contracts/doit/doit.dart @@ -0,0 +1,4 @@ +export 'DoitRINGDevice.g.dart' hide Initialized, OwnershipTransferred; +// export 'DoitRINGFriend.g.dart'; +// export 'DoitRINGStake.g.dart'; +// export 'BlueberryRingNFT.g.dart'; \ No newline at end of file diff --git a/packages/ens_dart/lib/src/json/BlueberryRingNFT.abi.json b/packages/ens_dart/lib/src/json/BlueberryRingNFT.abi.json new file mode 100644 index 00000000..5dd3f530 --- /dev/null +++ b/packages/ens_dart/lib/src/json/BlueberryRingNFT.abi.json @@ -0,0 +1,773 @@ +[ + { + "inputs": [], + "name": "MXCCollection__BurnMintError", + "type": "error" + }, + { + "inputs": [], + "name": "MXCCollection__NotAuthorize", + "type": "error" + }, + { + "inputs": [], + "name": "MXCCollection__NotCreator", + "type": "error" + }, + { + "inputs": [], + "name": "MXCCollection__NotExistToken", + "type": "error" + }, + { + "inputs": [], + "name": "MXCCollection__NotOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MXCCollection__StakedTokenTransferFailed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nft", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "burnMXC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_tokenURI", + "type": "string" + } + ], + "name": "burnMXCMint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "creator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "existSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBurnMXC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_tokenURI", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "gift", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_creator", + "type": "address" + }, + { + "internalType": "address", + "name": "_royaltyRecipient", + "type": "address" + }, + { + "internalType": "address", + "name": "_collateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_royaltiesCutPerMillion", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "initializeERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_tokenURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "royaltiesCutPerMillion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_salePrice", + "type": "uint256" + } + ], + "name": "royaltyInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "royaltyAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "royaltyRecipient", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "royaltyRecipientAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setBurnMXC", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "setTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nft", + "type": "uint256" + } + ], + "name": "stakedBalanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/ens_dart/lib/src/json/DoitRINGDevice.abi.json b/packages/ens_dart/lib/src/json/DoitRINGDevice.abi.json new file mode 100644 index 00000000..92cb4fb8 --- /dev/null +++ b/packages/ens_dart/lib/src/json/DoitRINGDevice.abi.json @@ -0,0 +1,695 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimInvalidClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "DeviceEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "DeviceRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "DeviceUnregistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "sncode", + "type": "string" + } + ], + "name": "Binded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "sncode", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct DoitRINGDevice.Reward[]", + "name": "rewards", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "indexed": false, + "internalType": "int256", + "name": "blockHeight", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "sncode", + "type": "string" + }, + { + "indexed": false, + "internalType": "int256", + "name": "blockHeight", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "Registered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uid", + "type": "string" + }, + { + "internalType": "string", + "name": "sncode", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct DoitRINGDevice.Reward[]", + "name": "rewards", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "claimInOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uid", + "type": "string" + }, + { + "internalType": "string", + "name": "sncode", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct DoitRINGDevice.Reward[]", + "name": "rewards", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "claimInSender", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "existsBinded", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getDeviceInAddress", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getDeviceInToken", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "height", + "type": "int256" + }, + { + "internalType": "string", + "name": "sncode", + "type": "string" + } + ], + "internalType": "struct DoitRINGDevice.DeviceMapping", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getTokenInAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "internalType": "struct DoitRINGDevice.TokenMapping", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sncode", + "type": "string" + } + ], + "name": "getTokenInDevice", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "internalType": "struct DoitRINGDevice.TokenMapping", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifier", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sncode", + "type": "string" + } + ], + "name": "rebind", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "sncode", + "type": "string" + } + ], + "name": "registerInSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/ens_dart/lib/src/json/DoitRINGFriend.abi.json b/packages/ens_dart/lib/src/json/DoitRINGFriend.abi.json new file mode 100644 index 00000000..78ac1c97 --- /dev/null +++ b/packages/ens_dart/lib/src/json/DoitRINGFriend.abi.json @@ -0,0 +1,846 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UserAlreadyInGroup", + "type": "error" + }, + { + "inputs": [], + "name": "UserNotInGroup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256" + } + ], + "name": "BatchMetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "group", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "GroupCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "group", + "type": "uint256" + } + ], + "name": "GroupJoined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "group", + "type": "uint256" + } + ], + "name": "GroupLeft", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "MetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "create", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "group", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifier", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupId", + "type": "uint256" + } + ], + "name": "join", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "leave", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userToGroup", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/ens_dart/lib/src/json/DoitRINGStake.abi.json b/packages/ens_dart/lib/src/json/DoitRINGStake.abi.json new file mode 100644 index 00000000..1a00e688 --- /dev/null +++ b/packages/ens_dart/lib/src/json/DoitRINGStake.abi.json @@ -0,0 +1,606 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "StakeAmountEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "StakeCancelEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "StakeCancelUnexpired", + "type": "error" + }, + { + "inputs": [], + "name": "StakeEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "StakeCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "StakeClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "StakeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "name": "Cancells", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "Stakes", + "outputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "index", + "type": "uint128" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "index", + "type": "uint128" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "create", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "index", + "type": "uint128" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "index", + "type": "uint128" + } + ], + "name": "expiration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "length", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "stakes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct IStake.Stake[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "index", + "type": "uint128" + } + ], + "name": "status", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/shared b/packages/shared index 09fe073a..af449b2e 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit 09fe073aa4e17559f95654da0e8248d307b3279c +Subproject commit af449b2e1974c3f5d763f86bc1df9eb0ae8d1b06 From 082c47a3282c2d17844538b8b5af917cb5547520 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 24 Jul 2024 11:27:37 +0330 Subject: [PATCH 11/45] feat: Blueberry ring helper --- .../utils/blueberry_ring_helper.dart | 84 +++++++++++++++++++ .../subfeatures/dapp_hooks/utils/utils.dart | 1 + 2 files changed, 85 insertions(+) create mode 100644 lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart diff --git a/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart b/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart new file mode 100644 index 00000000..a21dd8df --- /dev/null +++ b/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart @@ -0,0 +1,84 @@ +import 'package:datadashwallet/core/core.dart'; +import 'package:datadashwallet/features/common/common.dart'; +import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/utils/utils.dart'; +import 'package:datadashwallet/features/settings/subfeatures/notifications/domain/background_fetch_config_use_case.dart'; +import 'package:datadashwallet/features/settings/subfeatures/notifications/widgets/background_fetch_dialog.dart'; +import 'package:flutter/material.dart'; +import '../domain/dapp_hooks_use_case.dart'; + +class BlueberryHooksHelper { + BlueberryHooksHelper( + {required this.accountUseCase, + required this.dAppHooksUseCase, + required this.backgroundFetchConfigUseCase, + required this.context, + required this.translate}); + + DAppHooksUseCase dAppHooksUseCase; + BackgroundFetchConfigUseCase backgroundFetchConfigUseCase; + AccountUseCase accountUseCase; + DappHooksSnackBarUtils get dappHooksSnackBarUtils => + DappHooksSnackBarUtils(translate: translate, context: context); + BuildContext? context; + String? Function(String) translate; + + // delay is in minutes, returns true if success + Future startBlueberryRingHooksService( + {required DateTime time, required bool showBGFetchAlert}) async { + if (showBGFetchAlert) { + final res = await showBackgroundFetchAlertDialog(context: context!); + if (res == null || !res) { + return false; + } + } + + // Check Bluetooth & nearby devices enabled + // After all enabled start service + // listen for state and stop If the bluetooth & nearby device is went off + // The Service will listen to the ad data and do the things on that + final success = await dAppHooksUseCase.scheduleAutoClaimTransaction(time); + + if (success) { + // Time past, need to run the auto claim + + dappHooksSnackBarUtils.showBlueberryRingHooksServiceSuccessSnackBar(); + + return true; + } else { + dappHooksSnackBarUtils.showBlueberryRingHooksServiceFailureSnackBar(); + return false; + } + } + + Future stopBlueberryRingService({required bool showSnackbar}) async { + final dappHooksData = dAppHooksUseCase.dappHooksData.value; + final periodicalCallData = + backgroundFetchConfigUseCase.periodicalCallData.value; + final turnOffAll = + AXSBackgroundFetch.turnOffAll(dappHooksData, periodicalCallData); + + await dAppHooksUseCase.stopBlueberryAutoSyncService(turnOffAll: turnOffAll); + if (showSnackbar) { + dappHooksSnackBarUtils.showBlueberryRingHooksServiceFailureSnackBar(); + } + return true; + } + + Future changeMinerHooksEnabled( + bool value, + ) { + return DAppHooksHelper.shouldUpdateWrapper(() async { + late bool update; + if (value) { + update = await startBlueberryRingHooksService( + time: dAppHooksUseCase.dappHooksData.value.minerHooks.time, + showBGFetchAlert: true); + } else { + update = await stopBlueberryRingService(showSnackbar: true); + } + return update; + }, () { + return dAppHooksUseCase.updateMinerHooksEnabled(value); + }); + } +} diff --git a/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart b/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart index 2cb93f21..d49561ac 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart @@ -1,3 +1,4 @@ export 'miner_hooks_helper.dart'; export 'snack_bar_utils.dart'; export 'dapp_hooks_helper.dart'; +export 'blueberry_ring_helper.dart'; From 614ded89cb8b861c3888f2ed83462694f2ed79e8 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 24 Jul 2024 11:29:04 +0330 Subject: [PATCH 12/45] feat: Blueberry ring snack bars --- .../dapp_hooks/utils/snack_bar_utils.dart | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/features/settings/subfeatures/dapp_hooks/utils/snack_bar_utils.dart b/lib/features/settings/subfeatures/dapp_hooks/utils/snack_bar_utils.dart index c6118eef..e47d2eb3 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/utils/snack_bar_utils.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/utils/snack_bar_utils.dart @@ -52,6 +52,28 @@ class DappHooksSnackBarUtils { .replaceAll('{0}', translate('miner_hooks')!)); } + void showBlueberryRingHooksServiceFailureSnackBar() { + showSnackBar( + context: context!, + content: translate('unable_to_launch_service')! + .replaceAll('{0}', translate('blueberry_ring_hooks')!), + type: SnackBarType.fail); + } + + void showBlueberryRingHooksServiceSuccessSnackBar() { + showSnackBar( + context: context!, + content: translate('service_launched_successfully')! + .replaceAll('{0}', translate('blueberry_ring_hooks')!)); + } + + void showBlueberryRingHooksServiceDisableSuccessSnackBar() { + showSnackBar( + context: context!, + content: translate('service_disabled_successfully')! + .replaceAll('{0}', translate('blueberry_ring_hooks')!)); + } + void showScheduleSnackBar(String time) { showSnackBar( context: context!, From 1412f4241573d3d1bd7fe882644f30b7e8233cc9 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 13:13:40 +0330 Subject: [PATCH 13/45] test: Blueberry ring connection --- ...eberry_ring_background_notifications_use_case.dart | 8 ++++---- lib/features/settings/presentation/settings_page.dart | 2 +- .../presentation/settings_page_presenter.dart | 11 +++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart index 7973340c..a13ad0cf 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart @@ -27,7 +27,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkActivityReminder() async { final data = await _blueberryRingUseCase.readSteps(); - collectLog( + print( 'checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); // Get spteps data from cache and compare // If steps is below a certain number then show a @@ -52,7 +52,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkSleepInsight() async { final data = await _blueberryRingUseCase.readSleep(); - collectLog( + print( 'checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); // If sleeps is below standard level // loop throug all and get average @@ -86,7 +86,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkHeartAlert() async { final data = await _blueberryRingUseCase.readHeartRate(); - collectLog('checkHeartAlert:data ${data.map((e) => e.toJson()).toList()}'); + print('checkHeartAlert:data ${data.map((e) => e.toJson()).toList()}'); // If below standard but between person to person different final latestData = data.first; final lastDate = DateTime.fromMillisecondsSinceEpoch( @@ -108,7 +108,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkLowBattery() async { final data = await _blueberryRingUseCase.readLevel(); - collectLog('checkLowBattery:data $data'); + print('checkLowBattery:data $data'); // What si the low battery level // Is 10 OK if (data < 20) { diff --git a/lib/features/settings/presentation/settings_page.dart b/lib/features/settings/presentation/settings_page.dart index 0c72b89f..548c0454 100644 --- a/lib/features/settings/presentation/settings_page.dart +++ b/lib/features/settings/presentation/settings_page.dart @@ -37,7 +37,7 @@ class SettingsPage extends HookConsumerWidget { height: Sizes.space2XLarge, ), GestureDetector( - onTap: AXSFireBase.incrementBuildTap, + onTap: presenter.testOnly, child: Text( '${FlutterI18n.translate(context, 'app_version')}${state.appVersion ?? ''}', style: FontTheme.of(context) diff --git a/lib/features/settings/presentation/settings_page_presenter.dart b/lib/features/settings/presentation/settings_page_presenter.dart index ea9bad61..44d5e35a 100644 --- a/lib/features/settings/presentation/settings_page_presenter.dart +++ b/lib/features/settings/presentation/settings_page_presenter.dart @@ -15,6 +15,10 @@ class SettingsPresenter extends CompletePresenter { late final _webviewUseCase = WebviewUseCase(); late final _authUseCase = ref.read(authUseCaseProvider); late final _accountUserCase = ref.read(accountUseCaseProvider); + late final blueberryRingBackgroundNotificationsUseCase = + ref.read(blueberryRingBackgroundNotificationsUseCaseProvider); + late final contextLessTranslationUseCase = + ref.read(contextLessTranslationUseCaseProvider); @override void initState() { @@ -102,4 +106,11 @@ class SettingsPresenter extends CompletePresenter { void loadCache() { _webviewUseCase.clearCache(); } + + void testOnly() async { + await blueberryRingBackgroundNotificationsUseCase.checkActivityReminder(); + await blueberryRingBackgroundNotificationsUseCase.checkSleepInsight(); + await blueberryRingBackgroundNotificationsUseCase.checkHeartAlert(); + await blueberryRingBackgroundNotificationsUseCase.checkLowBattery(); + } } From 5e66996143c429a248bf92a92dfeea9f0b1287ba Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 13:42:02 +0330 Subject: [PATCH 14/45] fix: syntax --- .../domain/dapp_hooks_use_case.dart | 4 ++++ .../utils/blueberry_ring_helper.dart | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart index 66cdfee2..c28983c2 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart @@ -374,6 +374,10 @@ class DAppHooksUseCase extends ReactiveUseCase { return false; } } + Future stopBlueberryAutoSyncService({required bool turnOffAll}) async { + return await AXSBackgroundFetch.stopServices( + taskId: blueberryAutoSyncTask, turnOffAll: turnOffAll); + } Future stopMinerAutoClaimService({required bool turnOffAll}) async { return await AXSBackgroundFetch.stopServices( diff --git a/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart b/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart index a21dd8df..d3bab3ab 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/utils/blueberry_ring_helper.dart @@ -36,7 +36,8 @@ class BlueberryHooksHelper { // After all enabled start service // listen for state and stop If the bluetooth & nearby device is went off // The Service will listen to the ad data and do the things on that - final success = await dAppHooksUseCase.scheduleAutoClaimTransaction(time); + final success = + await dAppHooksUseCase.scheduleBlueberryAutoSyncTransaction(time); if (success) { // Time past, need to run the auto claim @@ -64,21 +65,36 @@ class BlueberryHooksHelper { return true; } - Future changeMinerHooksEnabled( + Future changeBLueberryRingHooksEnabled( bool value, ) { return DAppHooksHelper.shouldUpdateWrapper(() async { late bool update; if (value) { update = await startBlueberryRingHooksService( - time: dAppHooksUseCase.dappHooksData.value.minerHooks.time, + time: dAppHooksUseCase.dappHooksData.value.blueberryRingHooks.time, showBGFetchAlert: true); } else { update = await stopBlueberryRingService(showSnackbar: true); } return update; }, () { - return dAppHooksUseCase.updateMinerHooksEnabled(value); + return dAppHooksUseCase.updateBlueberryRingHooksEnabled(value); + }); + } + + Future changeBlueberryRingHookTiming(TimeOfDay value) async { + return DAppHooksHelper.shouldUpdateWrapper(() async { + late bool update; + final currentDateTime = + dAppHooksUseCase.dappHooksData.value.blueberryRingHooks.time; + final time = currentDateTime.copyWith( + hour: value.hour, minute: value.minute, second: 0); + update = await startBlueberryRingHooksService( + time: time, showBGFetchAlert: false); + return update; + }, () { + return dAppHooksUseCase.updateBlueberryRingHookTiming(value); }); } } From 25150980026706ab2c35d1547c9da4ca0a593521 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 13:50:04 +0330 Subject: [PATCH 15/45] feat: blueberry ring auto sync --- assets/flutter_i18n/en.json | 17 +- .../axs_background_fetch.dart | 4 +- .../dapp_hooks_service.dart | 44 +++++ ...lueberry_ring_bckground_sync_use_case.dart | 123 ++++++++++++ .../dapp_hooks/dapp_hooks_page.dart | 19 +- .../dapp_hooks/dapp_hooks_presenter.dart | 26 ++- .../domain/dapp_hooks_use_case.dart | 176 ++++++++++++++---- .../background_fetch_config_use_case.dart | 1 + 8 files changed, 372 insertions(+), 38 deletions(-) create mode 100644 lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart diff --git a/assets/flutter_i18n/en.json b/assets/flutter_i18n/en.json index 27e7fd11..0c17fa04 100644 --- a/assets/flutter_i18n/en.json +++ b/assets/flutter_i18n/en.json @@ -433,6 +433,19 @@ "low_battery": "Low battery", "blueberry_background_notifications_requirements_title": "This service requires: ", "blueberry_background_notifications_requirements_text_1": "1. Bluetooth to be ON", - "blueberry_background_notifications_requirements_text_2": "2. Blueberry to be reachable" - + "blueberry_background_notifications_requirements_text_2": "2. Blueberry to be reachable", + "auto_sync_started": "Blueberry Ring auto sync started 🏁", + "no_rings_selected_notification_title": "Looks like you haven't selected any Blueberry Rings. ℹ️", + "no_rings_selected_notification_text": "Please head over to Blueberry Ring DApp for selecting rings.", + "auto_sync_successful_notification_title": "Blueberry Ring aut-claim successful ✅", + "auto_sync_successful_notification_text": "AXS wallet has been successfully synced your ring data", + "already_synced_notification_title": "Oops, Already synced ℹ️", + "already_synced_notification_text": "AXS wallet tried to sync your ring data, But looks like you have synced the ring data today.", + "auto_sync_failed": "Blueberry Ring aut-sync failed ❌", + "no_rings_owned_notification": "Looks like this wallet doesn't own any Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Syncing data from Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Blueberry Ring #{0}: Already synced. ℹ️", + "data_synced_successfully_ring": "Blueberry Ring #{0}: Data synced successfully. ✅", + "data_syncing_failed": "Blueberry Ring #{0}: Data syncing process failed. ❌", + "blueberry_hooks": "Blueberry hooks" } \ No newline at end of file diff --git a/lib/core/src/background_process/axs_background_fetch.dart b/lib/core/src/background_process/axs_background_fetch.dart index b4edb33c..e4dc9428 100644 --- a/lib/core/src/background_process/axs_background_fetch.dart +++ b/lib/core/src/background_process/axs_background_fetch.dart @@ -28,6 +28,8 @@ class AXSBackgroundFetch { DAppHooksService.dappHooksServiceCallBackDispatcherForeground(taskId); } else if (taskId == BackgroundExecutionConfig.minerAutoClaimTask) { DAppHooksService.autoClaimServiceCallBackDispatcherForeground(taskId); + } else if (taskId == BackgroundExecutionConfig.blueberryAutoSyncTask) { + DAppHooksService.blueberryAutoSyncServiceCallBackDispatcherForeground(taskId); } else { bgFetch.BackgroundFetch.finish(taskId); } @@ -77,7 +79,7 @@ class AXSBackgroundFetch { requiresCharging: false, requiresStorageNotLow: false, requiresDeviceIdle: false, - requiredNetworkType: bgFetch.NetworkType.ANY), + requiredNetworkType: bgFetch.NetworkType.ANY,), handleCallBackDispatcher); // Android Only final backgroundFetchState = diff --git a/lib/core/src/background_process/dapp_hooks_service.dart b/lib/core/src/background_process/dapp_hooks_service.dart index 523d7535..744daede 100644 --- a/lib/core/src/background_process/dapp_hooks_service.dart +++ b/lib/core/src/background_process/dapp_hooks_service.dart @@ -66,6 +66,50 @@ class DAppHooksService { DAppHooksModel dappHooksData = dAppHooksUseCase.dappHooksData.value; final chainId = selectedNetwork.chainId; + final isLoggedIn = authUseCase.loggedIn; + final account = accountUseCase.account.value; + // final serviceEnabled = dappHooksData.enabled; + final minerHooksEnabled = dappHooksData.minerHooks.enabled; + final minerHooksTime = dappHooksData.minerHooks.time; + final selectedMiners = dappHooksData.minerHooks.selectedMiners; + // Make sure user is logged in + if (isLoggedIn && MXCChains.isMXCChains(chainId) && minerHooksEnabled) { + await AXSNotification() + .setupFlutterNotifications(shouldInitFirebase: false); + + await dAppHooksUseCase.executeMinerAutoClaim( + account: account!, + selectedMinerListId: selectedMiners, + minerAutoClaimTime: minerHooksTime); + BackgroundFetch.finish(taskId); + } else { + // terminate background fetch + BackgroundFetch.stop(taskId); + } + } catch (e) { + BackgroundFetch.finish(taskId); + } + } + + static void blueberryAutoSyncServiceCallBackDispatcherForeground( + String taskId) async { + try { + await loadProviders(); + + final container = ProviderContainer(); + final authUseCase = container.read(authUseCaseProvider); + final chainConfigurationUseCase = + container.read(chainConfigurationUseCaseProvider); + final accountUseCase = container.read(accountUseCaseProvider); + final dAppHooksUseCase = container.read(dAppHooksUseCaseProvider); + final contextLessTranslationUseCase = + container.read(contextLessTranslationUseCaseProvider); + + final selectedNetwork = + chainConfigurationUseCase.getCurrentNetworkWithoutRefresh(); + DAppHooksModel dappHooksData = dAppHooksUseCase.dappHooksData.value; + final chainId = selectedNetwork.chainId; + final isLoggedIn = authUseCase.loggedIn; final account = accountUseCase.account.value; // final serviceEnabled = dappHooksData.enabled; diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart new file mode 100644 index 00000000..a829071b --- /dev/null +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart @@ -0,0 +1,123 @@ +import 'dart:async'; +import 'dart:convert'; +import 'package:datadashwallet/features/common/common.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import 'package:datadashwallet/core/core.dart'; +import 'package:datadashwallet/features/settings/subfeatures/chain_configuration/domain/chain_configuration_use_case.dart'; + +import '../../../../../../app/logger.dart'; + +class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { + BlueberryRingBackgroundNotificationsUseCase( + this._repository, + this._chainConfigurationUseCase, + this._bluetoothUseCase, + this._blueberryRingUseCase, + this._accountUserCase, + this._contextLessTranslationUseCase); + + final Web3Repository _repository; + final ChainConfigurationUseCase _chainConfigurationUseCase; + final BluetoothUseCase _bluetoothUseCase; + final BlueberryRingUseCase _blueberryRingUseCase; + final AccountUseCase _accountUserCase; + final ContextLessTranslationUseCase _contextLessTranslationUseCase; + + + // Context less translation, This should be only used for BG functions + String cTranslate(String key) => + _contextLessTranslationUseCase.translate(key); + + + Future sendSyncTransaction({ + required BlueberryRingMiner ring, + required Account account, + required void Function(String title, String? text) showNotification, + required String Function( + String key, + ) + translate, + }) async { + // Get rings list + + // showNotification( + // translate('no_token_to_claim_miner') + // .replaceFirst('{0}', miner.mep1004TokenId!), + // null, + // ); + // no_rings_owned_notification + // syncing_data_from_ring + // already_synced_ring + // data_synced_successfully_ring + // data_syncing_failed + final memo = await fetchRingData(); + + final postClaimRequest = PostClaimRequestModel( + sncode: ring.sncode, + sender: account.address, + ); + final postClaimResponse = await _repository.blueberryRingRepository.postClaim( + postClaimRequest, + ); + + final txSig = await _repository.blueberryRingRepository.sendSyncTransaction(account.privateKey, ring, postClaimResponse, memo); + + // showNotification( + // translate('no_token_to_claim_miner') + // .replaceFirst('{0}', miner.mep1004TokenId!), + // null, + // ); + + + } + + + Future fetchRingData() async { + collectLog('fetchRingData'); + + final sleep = await _blueberryRingUseCase.readSleep(); + final bloodOxygens = await _blueberryRingUseCase.readBloodOxygens(); + final steps = await _blueberryRingUseCase.readSteps(); + final heartRate = await _blueberryRingUseCase.readHeartRate(); + + final data = { + 'sleep': sleep.map((e) => e.toJson()).toList(), + 'steps': steps.map((e) => e.toJson()).toList(), + 'heartRate': heartRate.map((e) => e.toJson()).toList(), + 'bloodOxygens': bloodOxygens.map((e) => e.toJson()).toList(), + }; + + + final content = json.encode(data); + + collectLog('fetchRingData:content : $content'); + + final mep3355 = { + 'format': 'MEP-3355', + 'version': '1.0.0', + 'metadata': { + 'data_source': 'BlueberryRingV1', + 'data_collection_method': 'bluetooth', + 'preprocessing': 'weighted average of data', + }, + 'data': [ + { + 'type': 'sensor', + // 'content': await compress(content), + 'compression': 'brotli', + }, + ], + }; + + collectLog('fetchRingData:content : $mep3355'); + + final returndataMap = { + 'json': mep3355, + 'data': data, + }; + final returnDataJson = json.encode(returndataMap); + return returnDataJson; + } + +} diff --git a/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_page.dart b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_page.dart index cb5352ce..d3393042 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_page.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_page.dart @@ -125,11 +125,28 @@ class DAppHooksPage extends HookConsumerWidget { const SizedBox(height: Sizes.spaceNormal), MXCDropDown( key: const Key('minerHooksTimingDropDown'), - onTap: dappHooksPresenter.showTimePickerDialog, + onTap: dappHooksPresenter.showTimePickerMinerDialog, selectedItem: autoClaimTime, enabled: isMXCChains && dappHooksState.dAppHooksData!.minerHooks.enabled, ), + // const SizedBox(height: Sizes.spaceLarge), + // MXCSwitchRowItem( + // key: const Key('blueberryRingHookSwitch'), + // title: translate('blueberry_hooks'), + // value: dappHooksState.dAppHooksData!.blueberryRingHooks.enabled, + // onChanged: dappHooksPresenter.changeBlueberryHooksEnabled, + // enabled: isMXCChains, + // titleStyle: FontTheme.of(context).h6(), + // ), + // const SizedBox(height: Sizes.spaceNormal), + // MXCDropDown( + // key: const Key('BlueberryHooksTimingDropDown'), + // onTap: dappHooksPresenter.showTimePickerBlueberryRingDialog, + // selectedItem: autoClaimTime, + // enabled: + // isMXCChains && dappHooksState.dAppHooksData!.blueberryRingHooks.enabled, + // ), ], ); } diff --git a/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_presenter.dart b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_presenter.dart index 5e7ad2cd..90e83528 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_presenter.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks_presenter.dart @@ -38,6 +38,13 @@ class DAppHooksPresenter extends CompletePresenter accountUseCase: _accountUseCase, backgroundFetchConfigUseCase: _backgroundFetchConfigUseCase); + BlueberryHooksHelper get blueberryRingHooksHelper => BlueberryHooksHelper( + translate: translate, + context: context, + dAppHooksUseCase: _dAppHooksUseCase, + accountUseCase: _accountUseCase, + backgroundFetchConfigUseCase: _backgroundFetchConfigUseCase); + WiFiHooksHelper get wifiHooksHelper => WiFiHooksHelper( translate: translate, context: context, @@ -82,6 +89,9 @@ class DAppHooksPresenter extends CompletePresenter void changeMinerHooksEnabled(bool value) => minerHooksHelper.changeMinerHooksEnabled(value); + void changeBlueberryHooksEnabled(bool value) => + blueberryRingHooksHelper.changeBLueberryRingHooksEnabled(value); + void showWiFiHooksFrequency() { showWiFiHooksFrequencyBottomSheet(context!, onTap: wifiHooksHelper.handleFrequencyChange, @@ -89,8 +99,20 @@ class DAppHooksPresenter extends CompletePresenter state.dAppHooksData!.wifiHooks.duration)); } - void showTimePickerDialog() async { + void showTimePickerMinerDialog() async { final currentTimeOfDay = state.dAppHooksData!.minerHooks.time; + showTimePickerDialog( + currentTimeOfDay, minerHooksHelper.changeMinerHookTiming); + } + + void showTimePickerBlueberryRingDialog() async { + final currentTimeOfDay = state.dAppHooksData!.blueberryRingHooks.time; + showTimePickerDialog(currentTimeOfDay, + blueberryRingHooksHelper.changeBlueberryRingHookTiming); + } + + void showTimePickerDialog(DateTime currentTimeOfDay, + Future Function(TimeOfDay value) changeTimeFunction) async { final initialTime = TimeOfDay.fromDateTime(currentTimeOfDay); final newTimeOfDay = await showTimePicker( context: context!, @@ -99,7 +121,7 @@ class DAppHooksPresenter extends CompletePresenter ); if (newTimeOfDay != null) { - minerHooksHelper.changeMinerHookTiming(newTimeOfDay); + changeTimeFunction(newTimeOfDay); } } diff --git a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart index c28983c2..73eeb576 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart @@ -58,6 +58,8 @@ class DAppHooksUseCase extends ReactiveUseCase { String get wifiHookTasksTaskId => BackgroundExecutionConfig.wifiHooksTask; String get minerAutoClaimTaskTaskId => BackgroundExecutionConfig.minerAutoClaimTask; + String get blueberryAutoSyncTask => + BackgroundExecutionConfig.blueberryAutoSyncTask; void initialize() { _chainConfigurationUseCase.selectedNetwork.listen((network) { @@ -85,6 +87,34 @@ class DAppHooksUseCase extends ReactiveUseCase { updateItem(newDAppHooksData); } + void updateRingsList(List rings) { + final newDAppHooksData = dappHooksData.value.copyWith( + blueberryRingHooks: dappHooksData.value.blueberryRingHooks.copyWith( + selectedRings: rings, + ), + ); + updateItem(newDAppHooksData); + } + + void updateBlueberryRingHookTiming(TimeOfDay value) { + final newDAppHooksData = dappHooksData.value.copyWith( + blueberryRingHooks: dappHooksData.value.blueberryRingHooks.copyWith( + time: dappHooksData.value.blueberryRingHooks.time + .copyWith(hour: value.hour, minute: value.minute, second: 0), + ), + ); + updateItem(newDAppHooksData); + } + + void updateBlueberryRingHooksEnabled(bool value) { + final newDAppHooksData = dappHooksData.value.copyWith( + blueberryRingHooks: dappHooksData.value.blueberryRingHooks.copyWith( + enabled: value, + ), + ); + updateItem(newDAppHooksData); + } + void updateMinersList(List miners) { final newDAppHooksData = dappHooksData.value.copyWith( minerHooks: dappHooksData.value.minerHooks.copyWith( @@ -296,29 +326,7 @@ class DAppHooksUseCase extends ReactiveUseCase { // delay is in minutes Future startWifiHooksService(int delay) async { - try { - final result = await AXSBackgroundFetch.startBackgroundProcess( - taskId: wifiHookTasksTaskId); - - if (!result) return result; - - final scheduleState = - await bgFetch.BackgroundFetch.scheduleTask(bgFetch.TaskConfig( - taskId: BackgroundExecutionConfig.wifiHooksTask, - delay: delay * 60 * 1000, - periodic: true, - requiresNetworkConnectivity: true, - startOnBoot: true, - stopOnTerminate: false, - enableHeadless: true, - forceAlarmManager: false, - requiredNetworkType: bgFetch.NetworkType.ANY, - )); - - return scheduleState; - } catch (e) { - return false; - } + return await startPeriodicalBackgroundService(delay, wifiHookTasksTaskId); } bool isTimeReached(DateTime dateTime) { @@ -326,15 +334,27 @@ class DAppHooksUseCase extends ReactiveUseCase { return difference <= 15; } - // This function is called after execusion & for scheduling - Future scheduleAutoClaimTransaction( + Future scheduleTaskForExecution( DateTime dateTime, + Future Function(int delay) startServiceFunction, ) async { final difference = MXCTime.getMinutesDifferenceByDateTime(dateTime); final delay = difference.isNegative ? (24 * 60 + difference) : difference; - return await startAutoClaimService(delay); + return await startServiceFunction(delay); } + // This function is called after execusion & for scheduling + Future scheduleAutoClaimTransaction( + DateTime dateTime, + ) async => + scheduleTaskForExecution(dateTime, startAutoClaimService); + + // This function is called after execusion & for scheduling + Future scheduleBlueberryAutoSyncTransaction( + DateTime dateTime, + ) => + scheduleTaskForExecution(dateTime, startBlueberryAutoSyncService); + Future executeMinerAutoClaim( {required Account account, required List selectedMinerListId, @@ -348,17 +368,57 @@ class DAppHooksUseCase extends ReactiveUseCase { ); } - // delay is in minutes - Future startAutoClaimService(int delay) async { + Future executeBlueberryAutoSync( + {required Account account, + required List selectedMinerListId, + required DateTime minerAutoClaimTime}) async { + await claimMiners( + selectedMinerListId: dappHooksData.value.minerHooks.selectedMiners, + account: account, + minerAutoClaimTime: minerAutoClaimTime, + ); + return await scheduleBlueberryAutoSyncTransaction( + minerAutoClaimTime, + ); + } + + Future startPeriodicalBackgroundService( + int delay, String taskId) async { try { - final result = await AXSBackgroundFetch.startBackgroundProcess( - taskId: minerAutoClaimTaskTaskId); + final result = + await AXSBackgroundFetch.startBackgroundProcess(taskId: taskId); if (!result) return result; final scheduleState = await bgFetch.BackgroundFetch.scheduleTask(bgFetch.TaskConfig( - taskId: BackgroundExecutionConfig.minerAutoClaimTask, + taskId: taskId, + delay: delay * 60 * 1000, + periodic: true, + requiresNetworkConnectivity: true, + startOnBoot: true, + stopOnTerminate: false, + enableHeadless: true, + forceAlarmManager: false, + requiredNetworkType: bgFetch.NetworkType.ANY, + )); + + return scheduleState; + } catch (e) { + return false; + } + } + + Future startOneTimeBackgroundService(int delay, String taskId) async { + try { + final result = + await AXSBackgroundFetch.startBackgroundProcess(taskId: taskId); + + if (!result) return result; + + final scheduleState = + await bgFetch.BackgroundFetch.scheduleTask(bgFetch.TaskConfig( + taskId: taskId, delay: delay * 60 * 1000, periodic: false, requiresNetworkConnectivity: true, @@ -374,6 +434,17 @@ class DAppHooksUseCase extends ReactiveUseCase { return false; } } + + // delay is in minutes + Future startBlueberryAutoSyncService(int delay) async { + return await startOneTimeBackgroundService(delay, blueberryAutoSyncTask); + } + + // delay is in minutes + Future startAutoClaimService(int delay) async { + return await startOneTimeBackgroundService(delay, minerAutoClaimTaskTaskId); + } + Future stopBlueberryAutoSyncService({required bool turnOffAll}) async { return await AXSBackgroundFetch.stopServices( taskId: blueberryAutoSyncTask, turnOffAll: turnOffAll); @@ -401,7 +472,6 @@ class DAppHooksUseCase extends ReactiveUseCase { required Account account, required DateTime minerAutoClaimTime}) async { try { - AXSNotification() .showNotification(cTranslate('auto_claim_started'), null); @@ -437,6 +507,48 @@ class DAppHooksUseCase extends ReactiveUseCase { } } + // List of miners + Future syncBlueberryRing( + {required List selectedMinerListId, + required Account account, + required DateTime minerAutoClaimTime}) async { + try { + AXSNotification().showNotification(cTranslate('auto_sync_started'), null); + + if (selectedMinerListId.isEmpty) { + AXSNotification().showNotification( + cTranslate('no_rings_selected_notification_title'), + cTranslate('no_rings_selected_notification_text'), + ); + } else { + final ableToClaim = await _minerUseCase.claimMinersReward( + selectedMinerListId: selectedMinerListId, + account: account, + showNotification: AXSNotification().showLowPriorityNotification, + translate: cTranslate); + + if (ableToClaim) { + AXSNotification().showNotification( + cTranslate('auto_sync_successful_notification_title'), + cTranslate('auto_sync_successful_notification_text'), + ); + } else { + AXSNotification().showNotification( + cTranslate('already_synced_notification_title'), + cTranslate('already_synced_notification_text'), + ); + } + // Updating now date time + 1 day to set the timer for tomorrow + updateAutoClaimTime(minerAutoClaimTime); + } + } catch (e) { + _errorUseCase.handleBackgroundServiceError( + cTranslate('auto_sync_failed'), + e, + ); + } + } + Future updateAutoClaimTime(DateTime minerAutoClaimTime) async { final now = DateTime.now(); DateTime updatedAutoClaimTime = now.copyWith( diff --git a/lib/features/settings/subfeatures/notifications/domain/background_fetch_config_use_case.dart b/lib/features/settings/subfeatures/notifications/domain/background_fetch_config_use_case.dart index 7fb1fe2f..583dfa92 100644 --- a/lib/features/settings/subfeatures/notifications/domain/background_fetch_config_use_case.dart +++ b/lib/features/settings/subfeatures/notifications/domain/background_fetch_config_use_case.dart @@ -247,6 +247,7 @@ class BackgroundFetchConfigUseCase extends ReactiveUseCase { enableHeadless: true, forceAlarmManager: false, requiredNetworkType: bgFetch.NetworkType.ANY, + )); return scheduleState; From 7cc75e42a2e1cf3c5167b784cd64e18bdf62e54b Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 15:42:11 +0330 Subject: [PATCH 16/45] fix: Update shared --- packages/shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared b/packages/shared index af449b2e..40d92209 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit af449b2e1974c3f5d763f86bc1df9eb0ae8d1b06 +Subproject commit 40d922091d3f6c514b4e77677e919728816008c1 From e5558302feccf4e19fc0bd41070778d67b80a8d9 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 18:21:33 +0330 Subject: [PATCH 17/45] fix: Blueberry name filter --- .../blueberry_ring/domain/blueberry_ring_use_case.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 721697db..3c266314 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -56,6 +56,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { _bluetoothUseCase.startScanning( withServices: [bluetoothServiceUUID], // withNames: ['Mi Smart Band 4'], + withNames: ['2301'] + ); await Future.delayed(const Duration(seconds: 2), () async { From dbc4be4313edea6f02299577fab3e3a5b8c7afa4 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 26 Jul 2024 18:24:54 +0330 Subject: [PATCH 18/45] fix: Add with keywords --- .../blueberry_ring/domain/blueberry_ring_use_case.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 3c266314..b0c3b9ef 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -56,8 +56,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { _bluetoothUseCase.startScanning( withServices: [bluetoothServiceUUID], // withNames: ['Mi Smart Band 4'], - withNames: ['2301'] - + withNames: ['2301'], + withKeywords: ['2301'], ); await Future.delayed(const Duration(seconds: 2), () async { From 2846e848a0a5b15ee9e48c3d930b32b23727b6cd Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 08:01:25 +0330 Subject: [PATCH 19/45] fix: Data reading from char --- .../domain/blueberry_ring_use_case.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index b0c3b9ef..ea234730 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -151,7 +151,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readLevel(); collectLog('readLevel:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readLevel:value $value'); return BlueberryResolves.readLevel(Uint8List.fromList(value!)); }, @@ -164,7 +164,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readVersion(); collectLog('readVersion:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readVersion:value $value'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); }, @@ -177,7 +177,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readTime(); collectLog('readTime:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readTime:value $value'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); }, @@ -190,7 +190,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSleep(); collectLog('readSleep:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readSleep:value $value'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); }, @@ -203,7 +203,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readBloodOxygens(); collectLog('readBloodOxygens:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readBloodOxygens:value $value'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); }, @@ -216,7 +216,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSteps(); collectLog('readSteps:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readSteps:value $value'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); }, @@ -229,7 +229,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readHeartRates(); collectLog('readHeartRate:command $command'); await blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingCharacteristic.value?.read(); + final value = blueberryRingCharacteristic.value?.lastValue; collectLog('readHeartRate:value $value'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); }, From 13c052f23459d36e545ce010af37896463ce8075 Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 11:40:30 +0330 Subject: [PATCH 20/45] fix: Notif char value --- .../domain/blueberry_ring_use_case.dart | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index ea234730..250f933c 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -33,7 +33,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { late final ValueStream blueberryRingCharacteristic = reactive(null); late final ValueStream - blueberryRinCharacteristicNotifications = reactive(null); + blueberryRingNotificationsCharacteristic = reactive(null); late final ValueStream bluetoothStatus = reactive(BluetoothAdapterState.off); @@ -142,6 +142,21 @@ class BlueberryRingUseCase extends ReactiveUseCase { await getBlueberryRingCharacteristic(); } + final isBlueberryRingNotificationsCharacteristicAvailable = + blueberryRingNotificationsCharacteristic.hasValue; + collectLog( + 'checkEstablishment:isBlueberryRingNotificationsCharacteristicAvailable $isBlueberryRingNotificationsCharacteristicAvailable'); + if (!isBlueberryRingNotificationsCharacteristicAvailable) { + await getBlueberryRingNotificationsCharacteristic(); + } + + final isNotifying = blueberryRingNotificationsCharacteristic.value!.isNotifying; + collectLog( + 'checkEstablishment:isBlueberryRingNotificationsCharacteristicNotifiying $isNotifying'); + if (!isNotifying) { + blueberryRingNotificationsCharacteristic.value!.setNotifyValue(true); + } + return await func(); } @@ -150,9 +165,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readLevel(); collectLog('readLevel:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readLevel:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readLevel(Uint8List.fromList(value!)); }, ); @@ -163,9 +179,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readVersion(); collectLog('readVersion:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readVersion:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); }, ); @@ -176,9 +193,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readTime(); collectLog('readTime:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readTime:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); }, ); @@ -189,9 +207,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readSleep(); collectLog('readSleep:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readSleep:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); }, ); @@ -202,9 +221,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readBloodOxygens(); collectLog('readBloodOxygens:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readBloodOxygens:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); }, ); @@ -215,9 +235,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readSteps(); collectLog('readSteps:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readSteps:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); }, ); @@ -228,9 +249,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readHeartRates(); collectLog('readHeartRate:command $command'); - await blueberryRingCharacteristic.value?.write(command); - final value = blueberryRingCharacteristic.value?.lastValue; + blueberryRingCharacteristic.value?.write(command); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; collectLog('readHeartRate:value $value'); + collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); }, ); @@ -244,22 +266,31 @@ class BlueberryRingUseCase extends ReactiveUseCase { return resp; } - Future - getBlueberryRingCharacteristicNotifications() async { + + Future getBlueberryRingNotificationsCharacteristic() async { final service = await getBlueberryRingBluetoothService(); final resp = await _getBlueberryRingCharacteristic( service, bluetoothCharacteristicNotificationUUID); - update(blueberryRinCharacteristicNotifications, resp); + update(blueberryRingNotificationsCharacteristic, resp); return resp; } - Future startBlueberryRingCharacteristicNotifications() async { - final characteristicNotifications = - await getBlueberryRingCharacteristicNotifications(); - await characteristicNotifications.setNotifyValue(true); - characteristicNotifications.onValueReceived.listen((event) {}); - final value = characteristicNotifications.read(); - } + // Future + // getBlueberryRingCharacteristicNotifications() async { + // final service = await getBlueberryRingBluetoothService(); + // final resp = await _getBlueberryRingCharacteristic( + // service, bluetoothCharacteristicNotificationUUID); + // update(blueberryRinNotificationsCharacteristic, resp); + // return resp; + // } + + // Future startBlueberryRingCharacteristicNotifications() async { + // final characteristicNotifications = + // await getBlueberryRingCharacteristicNotifications(); + // await characteristicNotifications.setNotifyValue(true); + // characteristicNotifications.lastValueStream.listen((event) {}); + // final value = characteristicNotifications.read(); + // } Future _getBlueberryRingPrimaryService( Guid serviceUUID, From 675556bc02abb12895b6f6e6678e4fff87ada8e7 Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 13:09:39 +0330 Subject: [PATCH 21/45] fix: empty data --- .../domain/blueberry_ring_use_case.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 250f933c..49cb2571 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -166,7 +166,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readLevel(); collectLog('readLevel:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readLevel:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readLevel(Uint8List.fromList(value!)); @@ -180,7 +180,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readVersion(); collectLog('readVersion:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readVersion:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); @@ -194,7 +194,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readTime(); collectLog('readTime:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readTime:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); @@ -208,7 +208,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSleep(); collectLog('readSleep:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readSleep:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); @@ -222,7 +222,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readBloodOxygens(); collectLog('readBloodOxygens:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readBloodOxygens:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); @@ -236,7 +236,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSteps(); collectLog('readSteps:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readSteps:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); @@ -250,7 +250,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readHeartRates(); collectLog('readHeartRate:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.first; + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); collectLog('readHeartRate:value $value'); collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); From 48b43ddf06d1e2ddf36e9e3e588261f1beeb39c4 Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 14:01:26 +0330 Subject: [PATCH 22/45] fix: ring commands map --- .../domain/blueberry_ring_use_case.dart | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 49cb2571..f2c8f780 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -60,7 +60,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { withKeywords: ['2301'], ); - await Future.delayed(const Duration(seconds: 2), () async { + await Future.delayed(const Duration(seconds: 4), () async { final scanResults = _bluetoothUseCase.scanResults.value; if (scanResults.isNotEmpty) { // only one scan results @@ -166,9 +166,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readLevel(); collectLog('readLevel:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readLevel:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readLevel(Uint8List.fromList(value!)); }, ); @@ -180,9 +179,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readVersion(); collectLog('readVersion:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readVersion:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); }, ); @@ -194,9 +192,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readTime(); collectLog('readTime:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readTime:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); }, ); @@ -208,9 +205,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSleep(); collectLog('readSleep:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readSleep:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); }, ); @@ -222,9 +218,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readBloodOxygens(); collectLog('readBloodOxygens:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readBloodOxygens:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); }, ); @@ -236,9 +231,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSteps(); collectLog('readSteps:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readSteps:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); }, ); @@ -250,9 +244,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readHeartRates(); collectLog('readHeartRate:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty); + final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); collectLog('readHeartRate:value $value'); - collectLog('readLevel:lastValue ${blueberryRingNotificationsCharacteristic.value!.lastValue}'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); }, ); From 05caa21eba57db6b33192b397357bffb2d7374ff Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 17:26:51 +0330 Subject: [PATCH 23/45] feat: Add bluetooth connection handler --- .../blue_plus/bluetooth_use_case.dart | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart index 12efc251..43d44b2b 100644 --- a/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart +++ b/lib/features/common/packages/bluetooth/blue_plus/bluetooth_use_case.dart @@ -146,6 +146,31 @@ class BluetoothUseCase extends ReactiveUseCase { } } + Future connectionHandler(BluetoothDevice device) async { + int attempts = 0; + const maxAttempts = 4; + while (attempts < maxAttempts) { + try { + print('Attempt ${attempts + 1} to connect to device...'); + await device.connect(); + print('Connected to device successfully.'); + break; // Exit the loop if the connection is successful + } catch (e) { + if (e is FlutterBluePlusException && e.function == 'connect') { + attempts++; + print('Failed to connect. Attempt $attempts of $maxAttempts.'); + if (attempts >= maxAttempts) { + print('Max attempts reached. Could not connect to device.'); + break; + } + } else { + print('Unexpected error: $e'); + break; // Exit on unexpected errors + } + } + } + } + void startScanning({ List? withServices, List? withRemoteIds, From 4dac62e731ee638607bd7ec8dba3565b92206ac4 Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 17:28:19 +0330 Subject: [PATCH 24/45] fix: Integrate connection handler with blueberry use case --- .../blueberry_ring/domain/blueberry_ring_use_case.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index f2c8f780..09cd25aa 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -101,7 +101,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { } Future connectToBlueberryRing() async { - await selectedBlueberryRing.value!.device.connect(); + await _bluetoothUseCase.connectionHandler(selectedBlueberryRing.value!.device); } Future getBlueberryRingBluetoothService() async { @@ -126,7 +126,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { 'checkEstablishment:isBlueberryRingConnected $isBlueberryRingConnected'); if (!isBlueberryRingConnected) { - await selectedBlueberryRing.value?.device.connect(); + await _bluetoothUseCase.connectionHandler(selectedBlueberryRing.value!.device); isBlueberryRingConnected = selectedBlueberryRing.value?.device.isConnected ?? false; if (!isBlueberryRingConnected) { From ef18dce9ada76e3050278b7b68088e4a3a0917a4 Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 29 Jul 2024 17:30:12 +0330 Subject: [PATCH 25/45] fix: Integrate connection handler --- .../dapps/subfeatures/open_dapp/open_dapp_presenter.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 59546679..94959bfc 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -740,7 +740,8 @@ class OpenDAppPresenter extends CompletePresenter { Future> handleBluetoothRemoteGATTServerConnect( Map data) async { collectLog('handleBluetoothRemoteGATTServerConnect : $data'); - await state.selectedScanResult?.device.connect(); + + await _bluetoothUseCase.connectionHandler(state.selectedScanResult!.device); return BluetoothRemoteGATTServer( device: BluetoothDevice.getBluetoothDeviceFromScanResult( From 80ce9a815eb9cb272cc3c830c8354d1fa4fcfad4 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 30 Jul 2024 09:56:06 +0330 Subject: [PATCH 26/45] fix: Read battery --- .../domain/blueberry_ring_use_case.dart | 75 +++++++++++++++---- .../presentation/settings_page_presenter.dart | 2 +- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 09cd25aa..2a836632 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -101,7 +101,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { } Future connectToBlueberryRing() async { - await _bluetoothUseCase.connectionHandler(selectedBlueberryRing.value!.device); + await _bluetoothUseCase + .connectionHandler(selectedBlueberryRing.value!.device); } Future getBlueberryRingBluetoothService() async { @@ -126,7 +127,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { 'checkEstablishment:isBlueberryRingConnected $isBlueberryRingConnected'); if (!isBlueberryRingConnected) { - await _bluetoothUseCase.connectionHandler(selectedBlueberryRing.value!.device); + await _bluetoothUseCase + .connectionHandler(selectedBlueberryRing.value!.device); isBlueberryRingConnected = selectedBlueberryRing.value?.device.isConnected ?? false; if (!isBlueberryRingConnected) { @@ -150,7 +152,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { await getBlueberryRingNotificationsCharacteristic(); } - final isNotifying = blueberryRingNotificationsCharacteristic.value!.isNotifying; + final isNotifying = + blueberryRingNotificationsCharacteristic.value!.isNotifying; collectLog( 'checkEstablishment:isBlueberryRingNotificationsCharacteristicNotifiying $isNotifying'); if (!isNotifying) { @@ -165,10 +168,38 @@ class BlueberryRingUseCase extends ReactiveUseCase { () async { final command = BlueberryCommands.readLevel(); collectLog('readLevel:command $command'); + + // Prepare to listen for the response before writing + final Stream>? stream = + blueberryRingNotificationsCharacteristic.value?.lastValueStream; + if (stream == null) { + throw Exception('Value stream is not available.'); + } + + // Create a completer to handle the response + final Completer> completer = Completer>(); + + // Subscribe to the stream and filter for the specific command + final StreamSubscription> subscription = + stream.listen((element) { + if (element.isNotEmpty && element.first == command.first) { + collectLog('readLevel:value $element'); + if (!completer.isCompleted) { + completer.complete(element); + } + } + }); + blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + + // Wait for the expected value to be received + final List value = await completer.future; + + // Cancel the subscription to avoid memory leaks + await subscription.cancel(); + collectLog('readLevel:value $value'); - return BlueberryResolves.readLevel(Uint8List.fromList(value!)); + return BlueberryResolves.readLevel(Uint8List.fromList(value)); }, ); } @@ -179,7 +210,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readVersion(); collectLog('readVersion:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readVersion:value $value'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); }, @@ -192,7 +226,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readTime(); collectLog('readTime:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readTime:value $value'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); }, @@ -205,7 +242,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSleep(); collectLog('readSleep:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readSleep:value $value'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); }, @@ -218,7 +258,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readBloodOxygens(); collectLog('readBloodOxygens:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readBloodOxygens:value $value'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); }, @@ -231,7 +274,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readSteps(); collectLog('readSteps:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readSteps:value $value'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); }, @@ -244,7 +290,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { final command = BlueberryCommands.readHeartRates(); collectLog('readHeartRate:command $command'); blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic.value?.lastValueStream.firstWhere((element) => element.isNotEmpty && element.first == command.first); + final value = await blueberryRingNotificationsCharacteristic + .value?.lastValueStream + .firstWhere((element) => + element.isNotEmpty && element.first == command.first); collectLog('readHeartRate:value $value'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); }, @@ -259,8 +308,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { return resp; } - - Future getBlueberryRingNotificationsCharacteristic() async { + Future + getBlueberryRingNotificationsCharacteristic() async { final service = await getBlueberryRingBluetoothService(); final resp = await _getBlueberryRingCharacteristic( service, bluetoothCharacteristicNotificationUUID); diff --git a/lib/features/settings/presentation/settings_page_presenter.dart b/lib/features/settings/presentation/settings_page_presenter.dart index 44d5e35a..e44a0c78 100644 --- a/lib/features/settings/presentation/settings_page_presenter.dart +++ b/lib/features/settings/presentation/settings_page_presenter.dart @@ -108,9 +108,9 @@ class SettingsPresenter extends CompletePresenter { } void testOnly() async { + await blueberryRingBackgroundNotificationsUseCase.checkLowBattery(); await blueberryRingBackgroundNotificationsUseCase.checkActivityReminder(); await blueberryRingBackgroundNotificationsUseCase.checkSleepInsight(); await blueberryRingBackgroundNotificationsUseCase.checkHeartAlert(); - await blueberryRingBackgroundNotificationsUseCase.checkLowBattery(); } } From cb5f51200840f794ffa1d82925180d19074db52f Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 31 Jul 2024 09:06:10 +0330 Subject: [PATCH 27/45] refactor: Fetch data from ring --- .../domain/blueberry_ring_use_case.dart | 145 ++++-------------- 1 file changed, 28 insertions(+), 117 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 2a836632..928991bf 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -38,11 +38,6 @@ class BlueberryRingUseCase extends ReactiveUseCase { late final ValueStream bluetoothStatus = reactive(BluetoothAdapterState.off); - // if (state.selectedScanResult != null) { - // responseDevice = BluetoothDevice.getBluetoothDeviceFromScanResult( - // state.selectedScanResult!); - // } - void initBlueberryRingSelectedActions() { selectedBlueberryRing.listen((event) { if (event != null) { @@ -52,7 +47,6 @@ class BlueberryRingUseCase extends ReactiveUseCase { } Future getBlueberryRingBackground() async { - // if (bluetoothStatus.value == BluetoothAdapterState.off || bluetoothStatus.value = BluetoothAdapterState.unauthorized) _bluetoothUseCase.startScanning( withServices: [bluetoothServiceUUID], // withNames: ['Mi Smart Band 4'], @@ -163,18 +157,16 @@ class BlueberryRingUseCase extends ReactiveUseCase { return await func(); } - Future readLevel() async { - return checkEstablishment( + Future readData(Uint8List Function() getCommandFunc, String dataName, + T Function(Uint8List) resolveData) async { + return checkEstablishment( () async { - final command = BlueberryCommands.readLevel(); - collectLog('readLevel:command $command'); + final command = getCommandFunc(); + collectLog('read$dataName:command $command'); // Prepare to listen for the response before writing - final Stream>? stream = - blueberryRingNotificationsCharacteristic.value?.lastValueStream; - if (stream == null) { - throw Exception('Value stream is not available.'); - } + final Stream> stream = + blueberryRingNotificationsCharacteristic.value!.lastValueStream; // Create a completer to handle the response final Completer> completer = Completer>(); @@ -183,7 +175,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { final StreamSubscription> subscription = stream.listen((element) { if (element.isNotEmpty && element.first == command.first) { - collectLog('readLevel:value $element'); + collectLog('read$dataName:value $element'); if (!completer.isCompleted) { completer.complete(element); } @@ -198,107 +190,35 @@ class BlueberryRingUseCase extends ReactiveUseCase { // Cancel the subscription to avoid memory leaks await subscription.cancel(); - collectLog('readLevel:value $value'); - return BlueberryResolves.readLevel(Uint8List.fromList(value)); + collectLog('read$dataName:value $value'); + return resolveData(Uint8List.fromList(value)); }, ); } - Future readVersion() async { - return checkEstablishment( - () async { - final command = BlueberryCommands.readVersion(); - collectLog('readVersion:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readVersion:value $value'); - return BlueberryResolves.readVersion(Uint8List.fromList(value!)); - }, - ); - } + Future readLevel() async => readData( + BlueberryCommands.readLevel, 'Level', BlueberryResolves.readLevel); - Future readTime() async { - return checkEstablishment( - () async { - final command = BlueberryCommands.readTime(); - collectLog('readTime:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readTime:value $value'); - return BlueberryResolves.readTime(Uint8List.fromList(value!)); - }, - ); - } + Future readVersion() async => readData( + BlueberryCommands.readVersion, 'Version', BlueberryResolves.readVersion); - Future> readSleep() async { - return checkEstablishment>( - () async { - final command = BlueberryCommands.readSleep(); - collectLog('readSleep:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readSleep:value $value'); - return BlueberryResolves.readSleep(Uint8List.fromList(value!)); - }, - ); - } + Future readTime() async => readData( + BlueberryCommands.readTime, 'Time', BlueberryResolves.readTime); - Future> readBloodOxygens() async { - return checkEstablishment>( - () async { - final command = BlueberryCommands.readBloodOxygens(); - collectLog('readBloodOxygens:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readBloodOxygens:value $value'); - return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); - }, - ); - } + Future> readSleep() async => + readData>( + BlueberryCommands.readSleep, 'Sleep', BlueberryResolves.readSleep); - Future> readSteps() async { - return checkEstablishment>( - () async { - final command = BlueberryCommands.readSteps(); - collectLog('readSteps:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readSteps:value $value'); - return BlueberryResolves.readSteps(Uint8List.fromList(value!)); - }, - ); - } + Future> readBloodOxygens() async => + readData>(BlueberryCommands.readBloodOxygens, + 'BloodOxygens', BlueberryResolves.readBloodOxygens); - Future> readHeartRate() async { - return checkEstablishment>( - () async { - final command = BlueberryCommands.readHeartRates(); - collectLog('readHeartRate:command $command'); - blueberryRingCharacteristic.value?.write(command); - final value = await blueberryRingNotificationsCharacteristic - .value?.lastValueStream - .firstWhere((element) => - element.isNotEmpty && element.first == command.first); - collectLog('readHeartRate:value $value'); - return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); - }, - ); - } + Future> readSteps() async => readData>( + BlueberryCommands.readSteps, 'Steps', BlueberryResolves.readSteps); + + Future> readHeartRate() async => + readData>(BlueberryCommands.readHeartRates, + 'HeartRate', BlueberryResolves.readHeartRates); Future getBlueberryRingCharacteristic() async { final service = await getBlueberryRingBluetoothService(); @@ -317,15 +237,6 @@ class BlueberryRingUseCase extends ReactiveUseCase { return resp; } - // Future - // getBlueberryRingCharacteristicNotifications() async { - // final service = await getBlueberryRingBluetoothService(); - // final resp = await _getBlueberryRingCharacteristic( - // service, bluetoothCharacteristicNotificationUUID); - // update(blueberryRinNotificationsCharacteristic, resp); - // return resp; - // } - // Future startBlueberryRingCharacteristicNotifications() async { // final characteristicNotifications = // await getBlueberryRingCharacteristicNotifications(); From 795d47bf292febe1512c308439cf092dc426ef67 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 1 Aug 2024 16:40:15 +0330 Subject: [PATCH 28/45] fix: BG fetch data retrieval chunks --- .../domain/blueberry_ring_use_case.dart | 59 ++++++++++++++----- .../utils/blueberry_commands_utils.dart | 3 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 928991bf..096e0807 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -158,7 +158,7 @@ class BlueberryRingUseCase extends ReactiveUseCase { } Future readData(Uint8List Function() getCommandFunc, String dataName, - T Function(Uint8List) resolveData) async { + T Function(Uint8List) resolveData, bool isFrag) async { return checkEstablishment( () async { final command = getCommandFunc(); @@ -171,13 +171,29 @@ class BlueberryRingUseCase extends ReactiveUseCase { // Create a completer to handle the response final Completer> completer = Completer>(); + Timer? timer; + List data = []; + // Subscribe to the stream and filter for the specific command final StreamSubscription> subscription = stream.listen((element) { if (element.isNotEmpty && element.first == command.first) { + timer?.cancel(); collectLog('read$dataName:value $element'); - if (!completer.isCompleted) { - completer.complete(element); + data.addAll(element); + collectLog('read$dataName:value $data'); + + if (!completer.isCompleted && !isFrag) { + completer.complete(data); + } else if (!completer.isCompleted && + isFrag && + element.last == 255) { + completer.complete(data); + } else { + timer = Timer( + const Duration(milliseconds: 5000), + () => completer.complete(data), + ); } } }); @@ -196,29 +212,44 @@ class BlueberryRingUseCase extends ReactiveUseCase { ); } - Future readLevel() async => readData( - BlueberryCommands.readLevel, 'Level', BlueberryResolves.readLevel); + Future readLevel() async => readData(BlueberryCommands.readLevel, + 'Level', BlueberryResolves.readLevel, BlueberryMethods.readLevel.frag); Future readVersion() async => readData( - BlueberryCommands.readVersion, 'Version', BlueberryResolves.readVersion); + BlueberryCommands.readVersion, + 'Version', + BlueberryResolves.readVersion, + BlueberryMethods.readVersion.frag); Future readTime() async => readData( - BlueberryCommands.readTime, 'Time', BlueberryResolves.readTime); + BlueberryCommands.readTime, + 'Time', + BlueberryResolves.readTime, + BlueberryMethods.readTime.frag); Future> readSleep() async => - readData>( - BlueberryCommands.readSleep, 'Sleep', BlueberryResolves.readSleep); + readData>(BlueberryCommands.readSleep, 'Sleep', + BlueberryResolves.readSleep, BlueberryMethods.readSleep.frag); Future> readBloodOxygens() async => - readData>(BlueberryCommands.readBloodOxygens, - 'BloodOxygens', BlueberryResolves.readBloodOxygens); + readData>( + BlueberryCommands.readBloodOxygens, + 'BloodOxygens', + BlueberryResolves.readBloodOxygens, + BlueberryMethods.readBloodOxygens.frag); Future> readSteps() async => readData>( - BlueberryCommands.readSteps, 'Steps', BlueberryResolves.readSteps); + BlueberryCommands.readSteps, + 'Steps', + BlueberryResolves.readSteps, + BlueberryMethods.readSteps.frag); Future> readHeartRate() async => - readData>(BlueberryCommands.readHeartRates, - 'HeartRate', BlueberryResolves.readHeartRates); + readData>( + BlueberryCommands.readHeartRates, + 'HeartRate', + BlueberryResolves.readHeartRates, + BlueberryMethods.readHeartRates.frag); Future getBlueberryRingCharacteristic() async { final service = await getBlueberryRingBluetoothService(); diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart index 78d0ef09..5f079853 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart @@ -3,8 +3,9 @@ import 'dart:typed_data'; class Method { final int uid; final List? arg; + final bool frag; - Method({required this.uid, this.arg}); + Method({required this.uid, this.arg, this.frag = false}); } class BlueberryCommandsUtils { From a4b242bafe4f294a9fa5125d77fa455e75a19f87 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 1 Aug 2024 16:40:46 +0330 Subject: [PATCH 29/45] feat: Methods config update --- .../bluetooth/blueberry_ring/utils/blueberry_configs.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart index 6dcc2e70..4757063b 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_configs.dart @@ -15,11 +15,11 @@ class GetMappings { class BlueberryMethods { static final readLevel = Method(uid: 0x13, arg: [1]); static final readVersion = Method(uid: 0x27); - static final readSteps = Method(uid: 0x52, arg: [1]); static final readTime = Method(uid: 0x41); - static final readSleep = Method(uid: 0x53, arg: [1, 2, 3]); - static final readHeartRates = Method(uid: 0x55, arg: [1, 2, 3]); - static final readBloodOxygens = Method(uid: 0x66, arg: [1, 2, 3]); + static final readSteps = Method(uid: 0x52, arg: [1], frag: true); + static final readSleep = Method(uid: 0x53, arg: [1, 2, 3], frag: true); + static final readHeartRates = Method(uid: 0x55, arg: [1, 2, 3], frag: true); + static final readBloodOxygens = Method(uid: 0x66, arg: [1, 2, 3], frag: true); static final writeTime = Method(uid: 0x01, arg: [1, 2, 3, 4, 5, 6]); static final writeRestore = Method(uid: 0x12, arg: []); } From 1da7bdd63cb5e42879f716ffd65911a68262e140 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 2 Aug 2024 12:17:50 +0330 Subject: [PATCH 30/45] fix: Improve logging --- .../blueberry_ring/domain/blueberry_ring_use_case.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 096e0807..3d1b34f8 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -179,9 +179,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { stream.listen((element) { if (element.isNotEmpty && element.first == command.first) { timer?.cancel(); - collectLog('read$dataName:value $element'); + collectLog('read$dataName:element $element'); data.addAll(element); - collectLog('read$dataName:value $data'); if (!completer.isCompleted && !isFrag) { completer.complete(data); From 751ce143dac9fc44ef3a720ac681df95769a2d17 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 2 Aug 2024 16:47:51 +0330 Subject: [PATCH 31/45] fix: List length error --- .../blueberry_ring/utils/blueberry_commands_utils.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart index 5f079853..79c5a1a2 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/utils/blueberry_commands_utils.dart @@ -24,7 +24,8 @@ class BlueberryCommandsUtils { static List> splitArrayByLength(List arr, int length) { List> result = []; for (int i = 0; i < arr.length; i += length) { - result.add(arr.sublist(i, i + length)); + int end = (i + length < arr.length) ? i + length : arr.length; + result.add(arr.sublist(i, end)); } return result; } From 56789254d720524a0ce6757d03da004fc3275e13 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 2 Aug 2024 16:50:14 +0330 Subject: [PATCH 32/45] fix: Today check ring notif --- ...ing_background_notifications_use_case.dart | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart index a13ad0cf..efd5154a 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart @@ -27,8 +27,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkActivityReminder() async { final data = await _blueberryRingUseCase.readSteps(); - print( - 'checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); + print('checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); // Get spteps data from cache and compare // If steps is below a certain number then show a // Below 5000 @@ -41,8 +40,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { now.month == lastDate.month && now.day == lastDate.day; - // isToday && - if (latestData.step < 5000) { + if (isToday && latestData.step < 5000) { AXSNotification().showNotification( cTranslate('activity_reminder'), cTranslate('blueberry_ring_inactive_alert_text'), @@ -52,23 +50,23 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkSleepInsight() async { final data = await _blueberryRingUseCase.readSleep(); - print( - 'checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); + print('checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); // If sleeps is below standard level // loop throug all and get average final now = DateTime.now(); final todaysData = data.where((element) { - // final date = DateTime.fromMillisecondsSinceEpoch( - // element.date * 1000, - // ); - // final isToday = now.year == date.year && - // now.month == date.month && - // now.day == date.day; - // return isToday; - return true; + final date = DateTime.fromMillisecondsSinceEpoch( + element.date * 1000, + ); + final isToday = now.year == date.year && + now.month == date.month && + now.day == date.day; + return isToday; }); + print( + 'checkSleepInsight:todaysData ${todaysData.map((e) => e.toJson()).toList()}'); if (todaysData.isEmpty) { return; } @@ -97,8 +95,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { now.month == lastDate.month && now.day == lastDate.day; - // isToday && - if (latestData.value >= 100) { + if (isToday && latestData.value >= 100) { AXSNotification().showNotification( cTranslate('heart_alert'), cTranslate('blueberry_ring_heart_rate_alert_text'), From 53c953ea9bfeb3fd39058320a43c459a57c5766b Mon Sep 17 00:00:00 2001 From: reasje Date: Mon, 5 Aug 2024 16:57:00 +0330 Subject: [PATCH 33/45] feat: Auto sync func imprv --- .../dapp_hooks_service.dart | 16 ++--- .../src/providers/providers_use_cases.dart | 13 ++++ ...eberry_ring_background_sync_use_case.dart} | 59 +++++++++++++------ .../blueberry_ring/domain/domain.dart | 1 + .../domain/dapp_hooks_use_case.dart | 41 +++++++------ 5 files changed, 84 insertions(+), 46 deletions(-) rename lib/features/common/packages/bluetooth/blueberry_ring/domain/{blueberry_ring_bckground_sync_use_case.dart => blueberry_ring_background_sync_use_case.dart} (65%) diff --git a/lib/core/src/background_process/dapp_hooks_service.dart b/lib/core/src/background_process/dapp_hooks_service.dart index 744daede..c2670c05 100644 --- a/lib/core/src/background_process/dapp_hooks_service.dart +++ b/lib/core/src/background_process/dapp_hooks_service.dart @@ -91,7 +91,7 @@ class DAppHooksService { } } - static void blueberryAutoSyncServiceCallBackDispatcherForeground( + static void blueberryAutoSyncServiceCallBackDispatcherForeground( String taskId) async { try { await loadProviders(); @@ -113,18 +113,18 @@ class DAppHooksService { final isLoggedIn = authUseCase.loggedIn; final account = accountUseCase.account.value; // final serviceEnabled = dappHooksData.enabled; - final minerHooksEnabled = dappHooksData.minerHooks.enabled; - final minerHooksTime = dappHooksData.minerHooks.time; - final selectedMiners = dappHooksData.minerHooks.selectedMiners; + final autoSyncEnabled = dappHooksData.blueberryRingHooks.enabled; + final ringHooksTime = dappHooksData.blueberryRingHooks.time; + final selectedRings = dappHooksData.blueberryRingHooks.selectedRings; // Make sure user is logged in - if (isLoggedIn && MXCChains.isMXCChains(chainId) && minerHooksEnabled) { + if (isLoggedIn && MXCChains.isMXCChains(chainId) && autoSyncEnabled) { await AXSNotification() .setupFlutterNotifications(shouldInitFirebase: false); - await dAppHooksUseCase.executeMinerAutoClaim( + await dAppHooksUseCase.syncBlueberryRingSync( account: account!, - selectedMinerListId: selectedMiners, - minerAutoClaimTime: minerHooksTime); + selectedRingsListId: selectedRings, + ringAutoSyncTime: ringHooksTime); BackgroundFetch.finish(taskId); } else { // terminate background fetch diff --git a/lib/core/src/providers/providers_use_cases.dart b/lib/core/src/providers/providers_use_cases.dart index 73539b21..8f1ad66c 100644 --- a/lib/core/src/providers/providers_use_cases.dart +++ b/lib/core/src/providers/providers_use_cases.dart @@ -146,6 +146,7 @@ final Provider dAppHooksUseCaseProvider = Provider( ), ref.watch(errorUseCaseProvider), ref.watch(contextLessTranslationUseCaseProvider), + ref.watch(blueberryRingBackgroundSyncUseCase), ), ); @@ -286,3 +287,15 @@ final Provider ref.watch(contextLessTranslationUseCaseProvider), ), ); + +final Provider + blueberryRingBackgroundSyncUseCase = Provider( + (ref) => BlueberryRingBackgroundSyncUseCase( + ref.watch(web3RepositoryProvider), + ref.watch(chainConfigurationUseCaseProvider), + ref.watch(bluetoothUseCaseProvider), + ref.watch(blueberryRingUseCaseProvider), + ref.watch(accountUseCaseProvider), + ref.watch(contextLessTranslationUseCaseProvider), + ), +); diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_sync_use_case.dart similarity index 65% rename from lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart rename to lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_sync_use_case.dart index a829071b..b12c42ce 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_bckground_sync_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_sync_use_case.dart @@ -8,8 +8,8 @@ import 'package:datadashwallet/features/settings/subfeatures/chain_configuration import '../../../../../../app/logger.dart'; -class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { - BlueberryRingBackgroundNotificationsUseCase( +class BlueberryRingBackgroundSyncUseCase extends ReactiveUseCase { + BlueberryRingBackgroundSyncUseCase( this._repository, this._chainConfigurationUseCase, this._bluetoothUseCase, @@ -30,8 +30,8 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { _contextLessTranslationUseCase.translate(key); - Future sendSyncTransaction({ - required BlueberryRingMiner ring, + Future syncRings({ + required List selectedRingsListId, required Account account, required void Function(String title, String? text) showNotification, required String Function( @@ -39,7 +39,26 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { ) translate, }) async { + // Get miner from cache + // for (String ring in selectedRings) { + + // } // Get rings list + // Get the data from contract +// async function arrayFilterDate(array: T[], date?: number) { +// if (!date) +// return array +// return array.filter((item: any) => item.date > (date || 0)) as T[] +// } +// arrayFilterDate(arr, detail.steps.at(-1)?.date) +// List arrayFilterDate(List array, {int? date}) { +// if (date == null) return array; + +// return array.where((item) { +// var itemDate = (item as dynamic).date; // Use 'dynamic' to access the 'date' property +// return itemDate > (date ?? 0); +// }).toList(); +// } // showNotification( // translate('no_token_to_claim_miner') @@ -51,27 +70,29 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { // already_synced_ring // data_synced_successfully_ring // data_syncing_failed - final memo = await fetchRingData(); + // final memo = await fetchRingData(); - final postClaimRequest = PostClaimRequestModel( - sncode: ring.sncode, - sender: account.address, - ); - final postClaimResponse = await _repository.blueberryRingRepository.postClaim( - postClaimRequest, - ); - - final txSig = await _repository.blueberryRingRepository.sendSyncTransaction(account.privateKey, ring, postClaimResponse, memo); - - // showNotification( - // translate('no_token_to_claim_miner') - // .replaceFirst('{0}', miner.mep1004TokenId!), - // null, + // final postClaimRequest = PostClaimRequestModel( + // sncode: ring.sncode, + // sender: account.address, + // ); + // final postClaimResponse = await _repository.blueberryRingRepository.postClaim( + // postClaimRequest, // ); + // final txSig = await _repository.blueberryRingRepository.sendSyncTransaction(account.privateKey, ring, postClaimResponse, memo); + // // showNotification( + // // translate('no_token_to_claim_miner') + // // .replaceFirst('{0}', miner.mep1004TokenId!), + // // null, + // // ); + + return true; } + Future syncRing(BlueberryRingMiner ring) async{} + Future fetchRingData() async { collectLog('fetchRingData'); diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/domain.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/domain.dart index 0453b11d..01bb0256 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/domain.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/domain.dart @@ -1,3 +1,4 @@ export 'blueberry_repository.dart'; export 'blueberry_ring_use_case.dart'; export 'blueberry_ring_background_notifications_use_case.dart'; +export 'blueberry_ring_background_sync_use_case.dart'; diff --git a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart index 73eeb576..dcd09e8d 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/domain/dapp_hooks_use_case.dart @@ -18,13 +18,15 @@ import 'dapp_hooks_repository.dart'; class DAppHooksUseCase extends ReactiveUseCase { DAppHooksUseCase( - this._repository, - this._chainConfigurationUseCase, - this._tokenContractUseCase, - this._minerUseCase, - this._accountUseCase, - this._errorUseCase, - this._contextLessTranslationUseCase) { + this._repository, + this._chainConfigurationUseCase, + this._tokenContractUseCase, + this._minerUseCase, + this._accountUseCase, + this._errorUseCase, + this._contextLessTranslationUseCase, + this._blueberryRingBackgroundSyncUseCase, + ) { initialize(); } @@ -35,6 +37,7 @@ class DAppHooksUseCase extends ReactiveUseCase { final ErrorUseCase _errorUseCase; final MinerUseCase _minerUseCase; final ContextLessTranslationUseCase _contextLessTranslationUseCase; + final BlueberryRingBackgroundSyncUseCase _blueberryRingBackgroundSyncUseCase; // Context less translation, This should be only used for BG functions String cTranslate(String key) => @@ -371,14 +374,14 @@ class DAppHooksUseCase extends ReactiveUseCase { Future executeBlueberryAutoSync( {required Account account, required List selectedMinerListId, - required DateTime minerAutoClaimTime}) async { - await claimMiners( - selectedMinerListId: dappHooksData.value.minerHooks.selectedMiners, + required DateTime ringAutoSyncTime}) async { + await syncBlueberryRingSync( + selectedRingsListId: dappHooksData.value.minerHooks.selectedMiners, account: account, - minerAutoClaimTime: minerAutoClaimTime, + ringAutoSyncTime: ringAutoSyncTime, ); return await scheduleBlueberryAutoSyncTransaction( - minerAutoClaimTime, + ringAutoSyncTime, ); } @@ -508,21 +511,21 @@ class DAppHooksUseCase extends ReactiveUseCase { } // List of miners - Future syncBlueberryRing( - {required List selectedMinerListId, + Future syncBlueberryRingSync( + {required List selectedRingsListId, required Account account, - required DateTime minerAutoClaimTime}) async { + required DateTime ringAutoSyncTime}) async { try { AXSNotification().showNotification(cTranslate('auto_sync_started'), null); - if (selectedMinerListId.isEmpty) { + if (selectedRingsListId.isEmpty) { AXSNotification().showNotification( cTranslate('no_rings_selected_notification_title'), cTranslate('no_rings_selected_notification_text'), ); } else { - final ableToClaim = await _minerUseCase.claimMinersReward( - selectedMinerListId: selectedMinerListId, + final ableToClaim = await _blueberryRingBackgroundSyncUseCase.syncRings( + selectedRingsListId: selectedRingsListId, account: account, showNotification: AXSNotification().showLowPriorityNotification, translate: cTranslate); @@ -539,7 +542,7 @@ class DAppHooksUseCase extends ReactiveUseCase { ); } // Updating now date time + 1 day to set the timer for tomorrow - updateAutoClaimTime(minerAutoClaimTime); + updateAutoClaimTime(ringAutoSyncTime); } } catch (e) { _errorUseCase.handleBackgroundServiceError( From 26e914cbea3c12039d6c569267747adc11d33df1 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 6 Aug 2024 09:42:26 +0330 Subject: [PATCH 34/45] feat: Wallet provider sign message --- assets/flutter_i18n/en.json | 3 +- .../contract/token_contract_use_case.dart | 5 ++ .../open_dapp/open_dapp_presenter.dart | 48 +++++++++++- .../open_dapp/widgets/message_info.dart | 78 +++++++++++++++++++ .../widgets/sign_message_bottom_sheet.dart | 52 +++++++++++++ .../open_dapp/widgets/widgets.dart | 2 + packages/shared | 2 +- 7 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/widgets/sign_message_bottom_sheet.dart diff --git a/assets/flutter_i18n/en.json b/assets/flutter_i18n/en.json index 0c17fa04..4a862b33 100644 --- a/assets/flutter_i18n/en.json +++ b/assets/flutter_i18n/en.json @@ -447,5 +447,6 @@ "already_synced_ring": "Blueberry Ring #{0}: Already synced. ℹ️", "data_synced_successfully_ring": "Blueberry Ring #{0}: Data synced successfully. ✅", "data_syncing_failed": "Blueberry Ring #{0}: Data syncing process failed. ❌", - "blueberry_hooks": "Blueberry hooks" + "blueberry_hooks": "Blueberry hooks", + "message": "Message" } \ No newline at end of file diff --git a/lib/features/common/contract/token_contract_use_case.dart b/lib/features/common/contract/token_contract_use_case.dart index 1839a9b7..16b98567 100644 --- a/lib/features/common/contract/token_contract_use_case.dart +++ b/lib/features/common/contract/token_contract_use_case.dart @@ -269,6 +269,11 @@ class TokenContractUseCase extends ReactiveUseCase { .getTokenTransferData(tokenHash, toAddress, amount); } + String signMessage({required String privateKey, required String message}) { + return _repository.tokenContract + .signMessage(privateKey: privateKey, message: message); + } + String signTypedMessage({required String privateKey, required String data}) { return _repository.tokenContract .signTypedMessage(privateKey: privateKey, data: data); diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 94959bfc..25ecd41f 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -165,6 +165,21 @@ class OpenDAppPresenter extends CompletePresenter { return res.hash; } + String? _signMessage( + String hexData, + ) { + loading = true; + try { + final res = _tokenContractUseCase.signMessage( + privateKey: state.account!.privateKey, message: hexData); + return res; + } catch (e, s) { + addError(e, s); + } finally { + loading = false; + } + } + String? _signTypedMessage( String hexData, ) { @@ -410,6 +425,38 @@ class OpenDAppPresenter extends CompletePresenter { void signPersonalMessage() {} + void signMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async { + final hexData = object['data'] as String; + String message = MXCType.hexToString(hexData); + int chainId = state.network!.chainId; + String name = state.network!.symbol; + + try { + final result = await showSignMessageDialog( + context!, + title: translate('signature_request')!, + message: message, + networkName: '$name ($chainId)', + ); + + if (result != null && result) { + final hash = _signMessage( + hexData, + ); + if (hash != null) success.call(hash); + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + addError(e, s); + } + } + void signTypedMessage({ required Map object, required VoidCallback cancel, @@ -740,7 +787,6 @@ class OpenDAppPresenter extends CompletePresenter { Future> handleBluetoothRemoteGATTServerConnect( Map data) async { collectLog('handleBluetoothRemoteGATTServerConnect : $data'); - await _bluetoothUseCase.connectionHandler(state.selectedScanResult!.device); return BluetoothRemoteGATTServer( diff --git a/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart b/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart new file mode 100644 index 00000000..efac3123 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart @@ -0,0 +1,78 @@ +import 'package:datadashwallet/common/common.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:mxc_ui/mxc_ui.dart'; + +import '../open_dapp_presenter.dart'; + +class MessageInfo extends ConsumerWidget { + const MessageInfo({ + Key? key, + required this.networkName, + required this.message, + this.onTap, + }) : super(key: key); + + final String networkName; + final String message; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final presenter = ref.read(openDAppPageContainer.actions); + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: Column( + children: [ + titleItem(context), + messageItem(context, presenter, message), + ], + ), + ), + const SizedBox(height: 8), + signButton(context), + ], + ); + } + + Widget signButton(BuildContext context) { + String titleText = 'sign'; + AxsButtonType type = AxsButtonType.primary; + + return MxcButton.primary( + key: const ValueKey('signButton'), + size: AxsButtonSize.xl, + title: FlutterI18n.translate(context, titleText), + type: type, + onTap: () { + if (onTap != null) onTap!(); + Navigator.of(context).pop(true); + }, + ); + } + + Widget titleItem(BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + networkName, + style: FontTheme.of(context).body2.secondary(), + softWrap: true, + ), + const SizedBox(height: 4), + ], + ) + ], + ); + } + + Widget messageItem(BuildContext context, OpenDAppPresenter presenter, String message) { + return SingleLineInfoItem(title: FlutterI18n.translate(context, 'message'), value: message); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/widgets/sign_message_bottom_sheet.dart b/lib/features/dapps/subfeatures/open_dapp/widgets/sign_message_bottom_sheet.dart new file mode 100644 index 00000000..74169c30 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/widgets/sign_message_bottom_sheet.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:mxc_ui/mxc_ui.dart'; + +import 'message_info.dart'; + +Future showSignMessageDialog( + BuildContext context, { + String? title, + required String networkName, + required String message, + VoidCallback? onTap, +}) { + return showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + isDismissible: false, + useSafeArea: true, + backgroundColor: Colors.transparent, + builder: (BuildContext context) => Container( + padding: const EdgeInsets.only(left: 16, right: 16, top: 0, bottom: 44), + decoration: BoxDecoration( + color: ColorsTheme.of(context).screenBackground, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + MxcAppBarEvenly.title( + titleText: title ?? '', + action: Container( + alignment: Alignment.centerRight, + child: InkWell( + child: const Icon(Icons.close), + onTap: () => Navigator.of(context).pop(false), + ), + ), + ), + MessageInfo( + message: message, + networkName: networkName, + onTap: onTap, + ), + const SizedBox(height: 10), + ], + ), + ), + ); +} diff --git a/lib/features/dapps/subfeatures/open_dapp/widgets/widgets.dart b/lib/features/dapps/subfeatures/open_dapp/widgets/widgets.dart index acbf5eb8..d3d1af6a 100644 --- a/lib/features/dapps/subfeatures/open_dapp/widgets/widgets.dart +++ b/lib/features/dapps/subfeatures/open_dapp/widgets/widgets.dart @@ -10,3 +10,5 @@ export 'transaction_dialog.dart'; export 'transaction_info.dart'; export 'typed_message_bottom_sheet.dart'; export 'typed_message_info.dart'; +export 'message_info.dart'; +export 'sign_message_bottom_sheet.dart'; diff --git a/packages/shared b/packages/shared index 40d92209..f949a958 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit 40d922091d3f6c514b4e77677e919728816008c1 +Subproject commit f949a95849bf50e688ccb0ca8e312eb598210317 From 3eb0c615b8bad41bf15fcbb2f7b1d868c9adf1ec Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 7 Aug 2024 11:34:09 +0330 Subject: [PATCH 35/45] refactor: JS channel, bluetooth channel, cron channel, panel --- .../subfeatures/open_dapp/domain/domain.dart | 4 + .../open_dapp/domain/helpers/helpers.dart | 1 + .../helpers/js_channels/bluetooth_helper.dart | 302 ++++++++ .../bluetooth_listeners_helper.dart | 100 +++ .../helpers/js_channels/cron_helper.dart | 137 ++++ .../js_channels/cron_listeners_helper.dart | 40 + .../helpers/js_channels/js_channel.dart | 5 + .../js_channel_handlers_helper.dart | 82 +++ .../utils/bluetooth_entities_utils.dart | 42 ++ .../domain/utils/js_channel_utils.dart | 29 + .../open_dapp/domain/utils/panel_utils.dart | 44 ++ .../open_dapp/domain/utils/utils.dart | 3 + .../subfeatures/open_dapp/open_dapp.dart | 5 + .../open_dapp/open_dapp_presenter.dart | 694 ++---------------- .../subfeatures/dapp_hooks/dapp_hooks.dart | 6 + .../subfeatures/dapp_hooks/domain/domain.dart | 2 + .../subfeatures/dapp_hooks/utils/utils.dart | 1 + .../widgets/{widget.dart => widgets.dart} | 0 18 files changed, 871 insertions(+), 626 deletions(-) create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/domain.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_listeners_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_listeners_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel_handlers_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/utils/bluetooth_entities_utils.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/utils/js_channel_utils.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/utils/panel_utils.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/open_dapp.dart create mode 100644 lib/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart create mode 100644 lib/features/settings/subfeatures/dapp_hooks/domain/domain.dart rename lib/features/settings/subfeatures/dapp_hooks/widgets/{widget.dart => widgets.dart} (100%) diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/domain.dart b/lib/features/dapps/subfeatures/open_dapp/domain/domain.dart new file mode 100644 index 00000000..2745a3a3 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/domain.dart @@ -0,0 +1,4 @@ +export 'utils/utils.dart'; +export 'helpers/helpers.dart'; +export 'entities/entities.dart'; +export 'dapps_errors.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart new file mode 100644 index 00000000..8d683965 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart @@ -0,0 +1 @@ +export 'js_channels/js_channel.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_helper.dart new file mode 100644 index 00000000..30077e87 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_helper.dart @@ -0,0 +1,302 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:collection/collection.dart'; +import 'package:datadashwallet/features/common/common.dart'; +import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart'; +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart' as blue_plus; + +import '../../../open_dapp.dart'; + +class BluetoothHelper { + BluetoothHelper({ + required this.state, + required this.context, + required this.translate, + required this.collectLog, + required this.bluetoothUseCase, + required this.navigator, + required this.minerHooksHelper, + required this.loading, + required this.characteristicListenerTimer, + required characteristicValueStreamSubscription, + }); + + OpenDAppState state; + BluetoothUseCase bluetoothUseCase; + void Function(String line) collectLog; + NavigatorState? navigator; + MinerHooksHelper minerHooksHelper; + BuildContext? context; + String? Function(String) translate; + void Function(bool v) loading; + Timer? characteristicListenerTimer; + StreamSubscription>? characteristicValueStreamSubscription; + + Future> handleBluetoothRequestDevice( + Map channelData, + ) async { + // final options = RequestDeviceOptions.fromJson(channelData['data']); + final options = RequestDeviceOptions.fromMap(channelData); + late BluetoothDevice responseDevice; + + await bluetoothUseCase.turnOnBluetoothAndProceed(); + + // Get the options data + bluetoothUseCase.startScanning( + withServices: options.filters != null + ? options.filters! + .expand((filter) => filter.services ?? []) + .toList() + .firstOrNull + : [], + withRemoteIds: + null, // No direct mapping in RequestDeviceOptions, adjust as necessary + withNames: options.filters != null + ? options.filters! + .where((filter) => filter.name != null) + .map((filter) => filter.name!) + .toList() + : [], + withKeywords: options.filters != null + ? options.filters! + .where((filter) => filter.namePrefix != null) + .map((filter) => filter.namePrefix!) + .toList() + : [], + withMsd: options.filters != null + ? options.filters! + .expand((filter) => filter.manufacturerData ?? []) + .toList() + .firstOrNull + : [], + withServiceData: options.filters != null + ? options.filters! + .expand((filter) => filter.serviceData ?? []) + .toList() + .firstOrNull + : [], + continuousUpdates: true, + continuousDivisor: 2, + androidUsesFineLocation: true, + ); + + final blueberryRing = await getBlueberryRing(); + bluetoothUseCase.stopScanner(); + if (blueberryRing == null) { + return {}; + } else { + responseDevice = blueberryRing; + } + + return responseDevice.toMap(); + } + + // GATT server + Future> handleBluetoothRemoteGATTServerGetPrimaryService( + Map data) async { + collectLog('handleBluetoothRemoteGATTServerGetPrimaryService : $data'); + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['service'], state.selectedScanResult!); + + final device = BluetoothDevice.getBluetoothDeviceFromScanResult( + state.selectedScanResult!); + final bluetoothRemoteGATTService = + BluetoothRemoteGATTService.fromBluetoothService( + device, selectedService); + return bluetoothRemoteGATTService.toMap(); + } + + void initJSCharacteristicValueEmitter( + blue_plus.BluetoothCharacteristic characteristic, + ) async { + await characteristic.setNotifyValue(true); + + characteristicValueStreamSubscription = + characteristic.lastValueStream.listen((event) async { + final uInt8List = Uint8List.fromList(event); + collectLog('characteristicValueStreamSubscription:event $event'); + collectLog( + 'characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}'); + final script = ''' + navigator.bluetooth.updateCharacteristicValue('${characteristic.uuid.str}', ${uInt8List.toString()},); + '''; + await state.webviewController!.evaluateJavascript(source: script); + }); + } + + void removeJSCharacteristicValueEmitter( + blue_plus.BluetoothCharacteristic characteristic, + ) async { + await characteristic.setNotifyValue(false); + + characteristicValueStreamSubscription?.cancel(); + } + + Future> handleBluetoothRemoteGATTServerConnect( + Map data) async { + collectLog('handleBluetoothRemoteGATTServerConnect : $data'); + await bluetoothUseCase.connectionHandler(state.selectedScanResult!.device); + + return BluetoothRemoteGATTServer( + device: BluetoothDevice.getBluetoothDeviceFromScanResult( + state.selectedScanResult!), + connected: true) + .toMap(); + } + + // Service + Future> + handleBluetoothRemoteGATTServiceGetCharacteristic( + Map data) async { + collectLog('handleBluetoothRemoteGATTServiceGetCharacteristic : $data'); + final targetCharacteristicUUID = data['characteristic']; + + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['this'], state.selectedScanResult!); + final targetCharacteristic = + BluetoothEntitiesUtils.getSelectedCharacteristic( + targetCharacteristicUUID, selectedService); + + final device = BluetoothDevice.getBluetoothDeviceFromScanResult( + state.selectedScanResult!); + final bluetoothRemoteGATTService = + BluetoothRemoteGATTService.fromBluetoothService( + device, selectedService); + final bluetoothRemoteGATTCharacteristic = BluetoothRemoteGATTCharacteristic( + service: bluetoothRemoteGATTService, + properties: + BluetoothCharacteristicProperties.fromCharacteristicProperties( + targetCharacteristic.properties), + uuid: targetCharacteristic.uuid.str, + value: null); + return bluetoothRemoteGATTCharacteristic.toMap(); + } + + Future> + handleBluetoothRemoteGATTCharacteristicStartNotifications( + Map data) async { + collectLog( + 'handleBluetoothRemoteGATTCharacteristicStartNotifications : $data'); + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['serviceUUID'], state.selectedScanResult!); + final selectedCharacteristic = + BluetoothEntitiesUtils.getSelectedCharacteristic( + data['this'], selectedService); + + final bluetoothRemoteGATTCharacteristic = + BluetoothEntitiesUtils.getBluetoothRemoteGATTCharacteristic( + selectedCharacteristic, selectedService, state.selectedScanResult!); + + initJSCharacteristicValueEmitter(selectedCharacteristic); + + return bluetoothRemoteGATTCharacteristic.toMap(); + } + + Future> + handleBluetoothRemoteGATTCharacteristicStopNotifications( + Map data) async { + collectLog( + 'handleBluetoothRemoteGATTCharacteristicStopNotifications : $data'); + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['serviceUUID'], state.selectedScanResult!); + final selectedCharacteristic = + BluetoothEntitiesUtils.getSelectedCharacteristic( + data['this'], selectedService); + + final bluetoothRemoteGATTCharacteristic = + BluetoothEntitiesUtils.getBluetoothRemoteGATTCharacteristic( + selectedCharacteristic, selectedService, state.selectedScanResult!); + + removeJSCharacteristicValueEmitter(selectedCharacteristic); + + return bluetoothRemoteGATTCharacteristic.toMap(); + } + + Future> handleWrites(Map data, + {bool withResponse = true}) async { + collectLog('handleWrites : $data'); + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['serviceUUID'], state.selectedScanResult!); + final selectedCharacteristic = + BluetoothEntitiesUtils.getSelectedCharacteristic( + data['this'], selectedService); + final value = Uint8List.fromList(List.from( + (data['value'] as Map).values.toList())); + + collectLog('handleWrites:value $value'); + if (withResponse) { + await selectedCharacteristic.write(value); + } else { + await selectedCharacteristic.write(value, withoutResponse: true); + } + return {}; + } + + Future> + handleBluetoothRemoteGATTCharacteristicWriteValue( + Map data) async { + return handleWrites(data); + } + + Future> + handleBluetoothRemoteGATTCharacteristicWriteValueWithResponse( + Map data) async { + return handleWrites(data); + } + + Future> + handleBluetoothRemoteGATTCharacteristicWriteValueWithoutResponse( + Map data) async { + return handleWrites(data, withResponse: false); + } + + Future handleBluetoothRemoteGATTCharacteristicReadValue( + Map data) async { + collectLog('handleBluetoothRemoteGATTCharacteristicReadValue : $data'); + final selectedService = await BluetoothEntitiesUtils.getSelectedService( + data['serviceUUID'], state.selectedScanResult!); + final selectedCharacteristic = + BluetoothEntitiesUtils.getSelectedCharacteristic( + data['this'], selectedService); + final value = selectedCharacteristic.lastValue; + + final uInt8List = Uint8List.fromList(value); + + collectLog('handleBluetoothRemoteGATTCharacteristicReadValue:value $value'); + collectLog( + 'handleBluetoothRemoteGATTCharacteristicReadValue:uInt8List ${uInt8List.toString()}'); + + return uInt8List; + } + + Future getBlueberryRing() async { + loading(true); + return Future.delayed(const Duration(seconds: 3), () async { + loading(false); + BluetoothDevice? responseDevice; + final scanResults = bluetoothUseCase.scanResults.value; + if (scanResults.length == 1) { + // only one scan results + final scanResult = scanResults.first; + state.selectedScanResult = scanResult; + } else { + // We need to let the user to choose If two or more devices of rings are available and even If empty maybe let the user to wait + final scanResult = await showBlueberryRingsBottomSheet( + context!, + ); + if (scanResult != null) { + state.selectedScanResult = scanResult; + } + } + if (state.selectedScanResult != null) { + responseDevice = BluetoothDevice.getBluetoothDeviceFromScanResult( + state.selectedScanResult!); + } + + return responseDevice; + }); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_listeners_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_listeners_helper.dart new file mode 100644 index 00000000..a0b81953 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/bluetooth_listeners_helper.dart @@ -0,0 +1,100 @@ +import 'package:datadashwallet/core/core.dart'; +import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart'; +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../../open_dapp.dart'; + +class BluetoothListenersHelper { + BluetoothListenersHelper({ + required this.state, + required this.context, + required this.translate, + required this.bluetoothHelper, + required this.navigator, + required this.minerHooksHelper, + required this.jsChannelHandlerHelper, + }); + + OpenDAppState state; + NavigatorState? navigator; + MinerHooksHelper minerHooksHelper; + BluetoothHelper bluetoothHelper; + BuildContext? context; + String? Function(String) translate; + JsChannelHandlersHelper jsChannelHandlerHelper; + + void injectBluetoothListeners() { + // Bluetooth API + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.requestDevice, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, bluetoothHelper.handleBluetoothRequestDevice)); + + // BluetoothRemoteGATTServer + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.bluetoothRemoteGATTServerConnect, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, bluetoothHelper.handleBluetoothRemoteGATTServerConnect)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.bluetoothRemoteGATTServerGetPrimaryService, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler(args, + bluetoothHelper.handleBluetoothRemoteGATTServerGetPrimaryService)); + + // BluetoothRemoteGATTService + + state.webviewController!.addJavaScriptHandler( + handlerName: + JSChannelEvents.bluetoothRemoteGATTServiceGetCharacteristic, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler(args, + bluetoothHelper.handleBluetoothRemoteGATTServiceGetCharacteristic)); + + // BluetoothRemoteGATTCharacteristic + + state.webviewController!.addJavaScriptHandler( + handlerName: + JSChannelEvents.bluetoothRemoteGATTCharacteristicStartNotifications, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, + bluetoothHelper + .handleBluetoothRemoteGATTCharacteristicStartNotifications)); + + state.webviewController!.addJavaScriptHandler( + handlerName: + JSChannelEvents.bluetoothRemoteGATTCharacteristicStopNotifications, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, + bluetoothHelper + .handleBluetoothRemoteGATTCharacteristicStopNotifications)); + + state.webviewController!.addJavaScriptHandler( + handlerName: + JSChannelEvents.bluetoothRemoteGATTCharacteristicWriteValue, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler(args, + bluetoothHelper.handleBluetoothRemoteGATTCharacteristicWriteValue)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents + .bluetoothRemoteGATTCharacteristicWriteValueWithResponse, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, + bluetoothHelper + .handleBluetoothRemoteGATTCharacteristicWriteValueWithResponse)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents + .bluetoothRemoteGATTCharacteristicWriteValueWithoutResponse, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler( + args, + bluetoothHelper + .handleBluetoothRemoteGATTCharacteristicWriteValueWithoutResponse)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.bluetoothRemoteGATTCharacteristicReadValue, + callback: (args) => jsChannelHandlerHelper.jsChannelErrorHandler(args, + bluetoothHelper.handleBluetoothRemoteGATTCharacteristicReadValue)); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_helper.dart new file mode 100644 index 00000000..a4f9ee78 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_helper.dart @@ -0,0 +1,137 @@ +import 'package:datadashwallet/core/core.dart'; +import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart'; +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../../open_dapp.dart'; + +class CronHelper { + CronHelper({ + required this.state, + required this.context, + required this.translate, + required this.dAppHooksUseCase, + required this.navigator, + required this.minerHooksHelper, + }); + + OpenDAppState state; + DAppHooksUseCase dAppHooksUseCase; + NavigatorState? navigator; + MinerHooksHelper minerHooksHelper; + BuildContext? context; + String? Function(String) translate; + + // Update via functions & get data via steam & send the data via event eaach time + // ready => updateSystemInfo (service statues, mining service status, time, selected miners, camera permission location permission) + + Future> handleChangeCronTransition( + Map channelData, AXSCronServices axsCronService) async { + final axsCronService = + AXSCronServicesExtension.getCronServiceFromJson(channelData); + if (axsCronService == AXSCronServices.miningAutoClaimCron) { + ChangeCronTransitionRequestModel; + final changeCronTransitionRequestModel = + ChangeCronTransitionRequestModel.fromMap( + channelData['cron'], MiningCronServiceDataModel.fromMap); + + // Here i change the data that won't effect the + final currentDappHooksData = state.dappHooksData; + final newData = changeCronTransitionRequestModel.data; + + if (newData != null) { + final minersList = newData.minersList ?? + currentDappHooksData.minerHooks.selectedMiners; + dAppHooksUseCase.updateMinersList(minersList); + + final newTimeOfDay = TimeOfDay.fromDateTime(newData.time!); + final currentTimeOfDay = + TimeOfDay.fromDateTime(currentDappHooksData.minerHooks.time); + + if (newData.time != null && newTimeOfDay != currentTimeOfDay) { + await minerHooksHelper.changeMinerHookTiming(newTimeOfDay); + } + } + + final miningCronServiceData = + MiningCronServiceDataModel.fromDAppHooksData( + dAppHooksUseCase.dappHooksData.value); + + final responseData = CronServiceDataModel.fromDAppHooksData( + axsCronService, + dAppHooksUseCase.dappHooksData.value, + miningCronServiceData); + + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.success, + data: responseData, + message: null); + return response.toMap(miningCronServiceData.toMapWrapper); + } else { + throw 'Unknown service'; + } + } + + Future> handleChangeCronTransitionStatusEvent( + Map channelData, + AXSCronServices axsCronService, + ) async { + if (axsCronService == AXSCronServices.miningAutoClaimCron) { + final status = channelData['cron']['status']; + + await minerHooksHelper.changeMinerHooksEnabled(status); + final miningCronServiceData = + MiningCronServiceDataModel.fromDAppHooksData( + dAppHooksUseCase.dappHooksData.value); + + final responseData = CronServiceDataModel.fromDAppHooksData( + axsCronService, + dAppHooksUseCase.dappHooksData.value, + miningCronServiceData); + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.success, + message: null, + data: responseData); + return response.toMap(miningCronServiceData.toMapWrapper); + } else { + throw 'Unknown cron service'; + } + } + + Future> handleGetSystemInfoEvent( + Map channelData, + AXSCronServices axsCronService, + ) async { + if (axsCronService == AXSCronServices.miningAutoClaimCron) { + final dappHooksData = state.dappHooksData; + + final miningCronServiceData = + MiningCronServiceDataModel.fromDAppHooksData(dappHooksData); + + final responseData = CronServiceDataModel.fromDAppHooksData( + axsCronService, dappHooksData, miningCronServiceData); + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.success, + message: null, + data: responseData, + ); + return response.toMap(miningCronServiceData.toMapWrapper); + } else { + throw 'Unknown cron service'; + } + } + + Future> handleGoToAdvancedSettingsEvent( + Map channelData, AXSCronServices axsCronService) async { + goToAdvancedSettings(); + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.success, message: null, data: null); + return response.toMap((data) => {}); + } + + void goToAdvancedSettings() { + navigator!.push(route( + const DAppHooksPage(), + )); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_listeners_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_listeners_helper.dart new file mode 100644 index 00000000..6281e32e --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/cron_listeners_helper.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../../open_dapp.dart'; + +class CronListenersHelper { + CronListenersHelper( + {required this.state, + required this.context, + required this.jsChannelHandlerHelper, + required this.cronHelper}); + + OpenDAppState state; + BuildContext? context; + JsChannelHandlersHelper jsChannelHandlerHelper; + CronHelper cronHelper; + + // call this on webview created + void injectMinerDappListeners() async { + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.changeCronTransitionEvent, + callback: (args) => jsChannelHandlerHelper.jsChannelCronErrorHandler( + args, cronHelper.handleChangeCronTransition)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.changeCronTransitionStatusEvent, + callback: (args) => jsChannelHandlerHelper.jsChannelCronErrorHandler( + args, cronHelper.handleChangeCronTransitionStatusEvent)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.getSystemInfoEvent, + callback: (args) => jsChannelHandlerHelper.jsChannelCronErrorHandler( + args, cronHelper.handleGetSystemInfoEvent)); + + state.webviewController!.addJavaScriptHandler( + handlerName: JSChannelEvents.goToAdvancedSettingsEvent, + callback: (args) => jsChannelHandlerHelper.jsChannelCronErrorHandler( + args, cronHelper.handleGoToAdvancedSettingsEvent)); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel.dart new file mode 100644 index 00000000..4a94f697 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel.dart @@ -0,0 +1,5 @@ +export 'cron_helper.dart'; +export 'bluetooth_helper.dart'; +export 'js_channel_handlers_helper.dart'; +export 'cron_listeners_helper.dart'; +export 'bluetooth_listeners_helper.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel_handlers_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel_handlers_helper.dart new file mode 100644 index 00000000..493b3975 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/js_channels/js_channel_handlers_helper.dart @@ -0,0 +1,82 @@ +import 'dart:convert'; + +import 'package:datadashwallet/features/common/packages/bluetooth/bluetooth.dart'; +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../../open_dapp.dart'; + +class JsChannelHandlersHelper { + JsChannelHandlersHelper({ + required this.state, + required this.context, + required this.translate, + required this.addError, + }); + + OpenDAppState state; + BuildContext? context; + String? Function(String) translate; + void Function(dynamic error, [StackTrace? stackTrace]) addError; + + + + Future> jsChannelCronErrorHandler( + List args, + Future> Function( + Map, + AXSCronServices, + ) + callback, + ) async { + try { + Map channelDataMap; + + final channelData = args[0]; + channelDataMap = channelData as Map; + + final axsCronService = + AXSCronServicesExtension.getCronServiceFromJson(channelDataMap); + final callbackRes = await callback(channelDataMap, axsCronService); + return callbackRes; + } catch (e) { + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.failed, + data: null, + message: e.toString()); + return response.toMap((data) => {'message': e.toString()}); + } + } + + Future jsChannelErrorHandler( + List args, + Future Function( + Map, + ) + callback, + ) async { + try { + Map channelDataMap; + + final channelData = args[0]; + channelDataMap = channelData == null + ? {} + : channelData is String + ? json.decode(channelData) as Map + : channelData as Map; + + final callbackRes = await callback(channelDataMap); + return callbackRes; + } catch (e) { + if (e is BluetoothTimeoutError) { + addError(translate('unable_to_continue_bluetooth_is_turned_off')!); + } + + final response = AXSJSChannelResponseModel( + status: AXSJSChannelResponseStatus.failed, + data: null, + message: e.toString()); + return response.toMap((data) => {'message': e}); + } + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/utils/bluetooth_entities_utils.dart b/lib/features/dapps/subfeatures/open_dapp/domain/utils/bluetooth_entities_utils.dart new file mode 100644 index 00000000..e4782644 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/utils/bluetooth_entities_utils.dart @@ -0,0 +1,42 @@ +import 'package:datadashwallet/features/common/packages/bluetooth/blue_plus/blue_plus.dart'; + +import '../../open_dapp.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart' as blue_plus; + +class BluetoothEntitiesUtils { + static BluetoothRemoteGATTCharacteristic getBluetoothRemoteGATTCharacteristic( + blue_plus.BluetoothCharacteristic selectedCharacteristic, + blue_plus.BluetoothService selectedService, + blue_plus.ScanResult selectedScanResult) { + final device = + BluetoothDevice.getBluetoothDeviceFromScanResult(selectedScanResult); + final bluetoothRemoteGATTService = + BluetoothRemoteGATTService.fromBluetoothService( + device, selectedService); + final bluetoothRemoteGATTCharacteristic = BluetoothRemoteGATTCharacteristic( + service: bluetoothRemoteGATTService, + properties: + BluetoothCharacteristicProperties.fromCharacteristicProperties( + selectedCharacteristic.properties), + uuid: selectedCharacteristic.uuid.str, + value: null); + return bluetoothRemoteGATTCharacteristic; + } + + static blue_plus.BluetoothCharacteristic getSelectedCharacteristic( + String uuid, blue_plus.BluetoothService selectedService) { + final characteristicUUID = GuidHelper.parse(uuid); + final selectedCharacteristic = + BluePlusBluetoothUtils.getCharacteristicWithService( + selectedService, characteristicUUID); + return selectedCharacteristic; + } + + static Future getSelectedService( + String uuid, blue_plus.ScanResult selectedScanResult) async { + final serviceUUID = GuidHelper.parse(uuid); + final selectedService = await BluePlusBluetoothUtils.getPrimaryService( + selectedScanResult, serviceUUID); + return selectedService; + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/utils/js_channel_utils.dart b/lib/features/dapps/subfeatures/open_dapp/domain/utils/js_channel_utils.dart new file mode 100644 index 00000000..45746ffa --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/utils/js_channel_utils.dart @@ -0,0 +1,29 @@ +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../open_dapp.dart'; + +class JSChannelUtils { + + + static void injectAXSWalletJSChannel(OpenDAppState state) async { + // Making It easy for accessing axs wallet + // use this way window.axs.callHandler + await state.webviewController!.evaluateJavascript( + source: JSChannelScripts.axsWalletObjectInjectScript( + JSChannelConfig.axsWalletJSObjectName)); + + await state.webviewController!.injectJavascriptFileFromAsset( + assetFilePath: 'assets/js/bluetooth/bluetooth.js'); + + // There is a gap for detecting the axs object in webview, It's intermittent after adding function structure to the scripts + Future.delayed( + const Duration(milliseconds: 500), + () async { + await state.webviewController!.evaluateJavascript( + source: JSChannelScripts.axsWalletReadyInjectScript( + JSChannelEvents.axsReadyEvent, + )); + }, + ); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/utils/panel_utils.dart b/lib/features/dapps/subfeatures/open_dapp/domain/utils/panel_utils.dart new file mode 100644 index 00000000..941c409b --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/utils/panel_utils.dart @@ -0,0 +1,44 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +import '../../open_dapp.dart'; + +const double maxPanelHeight = 100.0; + +const settleDuration = Duration(milliseconds: 400); +const cancelDuration = Duration(milliseconds: 400); + +class PanelUtils { + static void showPanel(OpenDAppState state, Timer? panelTimer) async { + final status = state.animationController!.status; + if (state.animationController!.value != 1 && + status == AnimationStatus.completed || + status == AnimationStatus.dismissed) { + await state.animationController!.animateTo( + 1.0, + duration: settleDuration, + curve: Curves.ease, + ); + panelTimer = Timer( + const Duration(seconds: 3), + () => hidePanel(state, panelTimer), + ); + } + } + + static void hidePanel(OpenDAppState state, Timer? panelTimer) async { + final status = state.animationController!.status; + if (state.animationController!.value != 0 && + status == AnimationStatus.completed) { + await state.animationController!.animateTo( + 0.0, + duration: cancelDuration, + curve: Curves.easeInExpo, + ); + if (panelTimer != null) { + panelTimer.cancel(); + } + } + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/utils/utils.dart b/lib/features/dapps/subfeatures/open_dapp/domain/utils/utils.dart index e69de29b..6426d551 100644 --- a/lib/features/dapps/subfeatures/open_dapp/domain/utils/utils.dart +++ b/lib/features/dapps/subfeatures/open_dapp/domain/utils/utils.dart @@ -0,0 +1,3 @@ +export 'bluetooth_entities_utils.dart'; +export 'js_channel_utils.dart'; +export 'panel_utils.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp.dart new file mode 100644 index 00000000..3f539d7a --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp.dart @@ -0,0 +1,5 @@ +export 'open_dapp_state.dart'; +export 'open_dapp_presenter.dart'; +export 'open_dapp_page.dart'; +export 'widgets/widgets.dart'; +export 'domain/domain.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 25ecd41f..4195c02b 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -1,26 +1,18 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:developer'; +import 'package:flutter/services.dart'; + import 'package:clipboard/clipboard.dart'; -import 'package:collection/collection.dart'; + import 'package:datadashwallet/app/logger.dart'; import 'package:datadashwallet/common/common.dart'; import 'package:datadashwallet/core/core.dart'; -import 'package:datadashwallet/features/common/common.dart'; -import 'package:datadashwallet/features/dapps/subfeatures/open_dapp/domain/dapps_errors.dart'; - -import 'package:datadashwallet/features/dapps/subfeatures/open_dapp/widgets/widgets.dart'; -import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/dapp_hooks_page.dart'; import 'package:datadashwallet/features/settings/subfeatures/dapp_hooks/utils/utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_blue_plus/flutter_blue_plus.dart' as blue_plus; + import 'package:mxc_logic/mxc_logic.dart'; import 'package:web3_provider/web3_provider.dart'; -import 'package:eth_sig_util/util/utils.dart'; -import './domain/entities/entities.dart'; -import 'open_dapp_state.dart'; +import 'open_dapp.dart'; final openDAppPageContainer = PresenterContainer( @@ -44,6 +36,9 @@ class OpenDAppPresenter extends CompletePresenter { ref.read(backgroundFetchConfigUseCaseProvider); late final _bluetoothUseCase = ref.read(bluetoothUseCaseProvider); + Timer? characteristicListenerTimer; + StreamSubscription>? characteristicValueStreamSubscription; + MinerHooksHelper get minerHooksHelper => MinerHooksHelper( translate: translate, context: context, @@ -52,6 +47,55 @@ class OpenDAppPresenter extends CompletePresenter { backgroundFetchConfigUseCase: _backgroundFetchConfigUseCase, ); + JsChannelHandlersHelper get jsChannelHandlersHelper => + JsChannelHandlersHelper( + translate: translate, + context: context, + state: state, + addError: addError, + ); + + CronHelper get cronHelper => CronHelper( + translate: translate, + context: context, + dAppHooksUseCase: _dAppHooksUseCase, + minerHooksHelper: minerHooksHelper, + navigator: navigator, + state: state, + ); + + BluetoothHelper get bluetoothHelper => BluetoothHelper( + translate: translate, + context: context, + collectLog: collectLog, + minerHooksHelper: minerHooksHelper, + navigator: navigator, + state: state, + loading: (bool value) => loading = value, + bluetoothUseCase: _bluetoothUseCase, + characteristicListenerTimer: characteristicListenerTimer, + characteristicValueStreamSubscription: + characteristicValueStreamSubscription, + ); + + CronListenersHelper get cronListenersHelper => CronListenersHelper( + context: context, + state: state, + cronHelper: cronHelper, + jsChannelHandlerHelper: jsChannelHandlersHelper, + ); + + BluetoothListenersHelper get bluetoothListenersHelper => + BluetoothListenersHelper( + translate: translate, + context: context, + bluetoothHelper: bluetoothHelper, + minerHooksHelper: minerHooksHelper, + jsChannelHandlerHelper: jsChannelHandlersHelper, + navigator: navigator, + state: state, + ); + @override void initState() { super.initState(); @@ -84,7 +128,7 @@ class OpenDAppPresenter extends CompletePresenter { @override Future dispose() { - characteriticListnerTimer?.cancel(); + cancelCharacteristicListenerTimer(); closeBlueberryConnection(); return super.dispose(); } @@ -97,8 +141,8 @@ class OpenDAppPresenter extends CompletePresenter { void onWebViewCreated(InAppWebViewController controller) async { notify(() => state.webviewController = controller); updateCurrentUrl(null); - injectMinerDappListeners(); - injectBluetoothListeners(); + cronListenersHelper.injectMinerDappListeners(); + bluetoothListenersHelper.injectBluetoothListeners(); } void updateCurrentUrl(Uri? value) async { @@ -237,7 +281,7 @@ class OpenDAppPresenter extends CompletePresenter { }) async { final amountEther = EtherAmount.inWei(bridge.value ?? BigInt.zero); final amount = amountEther.getValueInUnit(EtherUnit.ether).toString(); - final bridgeData = hexToBytes(bridge.data ?? ''); + final bridgeData = MXCType.hexToUint8List(bridge.data ?? ''); EtherAmount? gasPrice; double? gasFee; TransactionGasEstimation? estimatedGasFee; @@ -423,8 +467,7 @@ class OpenDAppPresenter extends CompletePresenter { return newNetwork; } - void signPersonalMessage() {} - + /// This function is used for both sign message and sign personal message void signMessage({ required Map object, required VoidCallback cancel, @@ -600,11 +643,6 @@ class OpenDAppPresenter extends CompletePresenter { return NavigationActionPolicy.ALLOW; } - final double maxPanelHeight = 100.0; - - final cancelDuration = const Duration(milliseconds: 400); - final settleDuration = const Duration(milliseconds: 400); - injectScrollDetector() { state.webviewController! .evaluateJavascript(source: JSChannelScripts.overScrollScript); @@ -621,34 +659,9 @@ class OpenDAppPresenter extends CompletePresenter { Timer? panelTimer; - void showPanel() async { - final status = state.animationController!.status; - if (state.animationController!.value != 1 && - status == AnimationStatus.completed || - status == AnimationStatus.dismissed) { - await state.animationController!.animateTo( - 1.0, - duration: settleDuration, - curve: Curves.ease, - ); - panelTimer = Timer(const Duration(seconds: 3), hidePanel); - } - } + void showPanel() => PanelUtils.showPanel(state, panelTimer); - void hidePanel() async { - final status = state.animationController!.status; - if (state.animationController!.value != 0 && - status == AnimationStatus.completed) { - await state.animationController!.animateTo( - 0.0, - duration: cancelDuration, - curve: Curves.easeInExpo, - ); - if (panelTimer != null) { - panelTimer!.cancel(); - } - } - } + void hidePanel() => PanelUtils.hidePanel(state, panelTimer); void closedApp() { navigator!.pop(); @@ -681,580 +694,9 @@ class OpenDAppPresenter extends CompletePresenter { state.isLoadStopCalled = !state.isLoadStopCalled; } - // call this on webview created - void injectMinerDappListeners() async { - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.changeCronTransitionEvent, - callback: (args) => - jsChannelCronErrorHandler(args, handleChangeCronTransition)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.changeCronTransitionStatusEvent, - callback: (args) => jsChannelCronErrorHandler( - args, handleChangeCronTransitionStatusEvent)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.getSystemInfoEvent, - callback: (args) => - jsChannelCronErrorHandler(args, handleGetSystemInfoEvent)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.goToAdvancedSettingsEvent, - callback: (args) => - jsChannelCronErrorHandler(args, handleGoToAdvancedSettingsEvent)); - } - - void injectBluetoothListeners() { - // Bluetooth API - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.requestDevice, - callback: (args) => - jsChannelErrorHandler(args, handleBluetoothRequestDevice)); - - // BluetoothRemoteGATTServer - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.bluetoothRemoteGATTServerConnect, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTServerConnect)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.bluetoothRemoteGATTServerGetPrimaryService, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTServerGetPrimaryService)); - - // BluetoothRemoteGATTService - - state.webviewController!.addJavaScriptHandler( - handlerName: - JSChannelEvents.bluetoothRemoteGATTServiceGetCharacteristic, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTServiceGetCharacteristic)); - - // BluetoothRemoteGATTCharacteristic - - state.webviewController!.addJavaScriptHandler( - handlerName: - JSChannelEvents.bluetoothRemoteGATTCharacteristicStartNotifications, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTCharacteristicStartNotifications)); - - state.webviewController!.addJavaScriptHandler( - handlerName: - JSChannelEvents.bluetoothRemoteGATTCharacteristicStopNotifications, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTCharacteristicStopNotifications)); - - state.webviewController!.addJavaScriptHandler( - handlerName: - JSChannelEvents.bluetoothRemoteGATTCharacteristicWriteValue, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTCharacteristicWriteValue)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents - .bluetoothRemoteGATTCharacteristicWriteValueWithResponse, - callback: (args) => jsChannelErrorHandler(args, - handleBluetoothRemoteGATTCharacteristicWriteValueWithResponse)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents - .bluetoothRemoteGATTCharacteristicWriteValueWithoutResponse, - callback: (args) => jsChannelErrorHandler(args, - handleBluetoothRemoteGATTCharacteristicWriteValueWithoutResponse)); - - state.webviewController!.addJavaScriptHandler( - handlerName: JSChannelEvents.bluetoothRemoteGATTCharacteristicReadValue, - callback: (args) => jsChannelErrorHandler( - args, handleBluetoothRemoteGATTCharacteristicReadValue)); - } - - // GATT server - Future> handleBluetoothRemoteGATTServerGetPrimaryService( - Map data) async { - collectLog('handleBluetoothRemoteGATTServerGetPrimaryService : $data'); - final selectedService = await getSelectedService(data['service']); - - final device = BluetoothDevice.getBluetoothDeviceFromScanResult( - state.selectedScanResult!); - final bluetoothRemoteGATTService = - BluetoothRemoteGATTService.fromBluetoothService( - device, selectedService); - return bluetoothRemoteGATTService.toMap(); - } - - Future> handleBluetoothRemoteGATTServerConnect( - Map data) async { - collectLog('handleBluetoothRemoteGATTServerConnect : $data'); - await _bluetoothUseCase.connectionHandler(state.selectedScanResult!.device); - - return BluetoothRemoteGATTServer( - device: BluetoothDevice.getBluetoothDeviceFromScanResult( - state.selectedScanResult!), - connected: true) - .toMap(); - } - - Future getSelectedService( - String uuid, - ) async { - final serviceUUID = GuidHelper.parse(uuid); - final selectedService = await BluePlusBluetoothUtils.getPrimaryService( - state.selectedScanResult!, serviceUUID); - return selectedService; - } - - // Util - blue_plus.BluetoothCharacteristic getSelectedCharacteristic( - String uuid, blue_plus.BluetoothService selectedService) { - final characteristicUUID = GuidHelper.parse(uuid); - final selectedCharacteristic = - BluePlusBluetoothUtils.getCharacteristicWithService( - selectedService, characteristicUUID); - return selectedCharacteristic; - } - - // Service - Future> - handleBluetoothRemoteGATTServiceGetCharacteristic( - Map data) async { - collectLog('handleBluetoothRemoteGATTServiceGetCharacteristic : $data'); - final targetCharacteristicUUID = data['characteristic']; - - final selectedService = await getSelectedService(data['this']); - final targetCharacteristic = - getSelectedCharacteristic(targetCharacteristicUUID, selectedService); - - final device = BluetoothDevice.getBluetoothDeviceFromScanResult( - state.selectedScanResult!); - final bluetoothRemoteGATTService = - BluetoothRemoteGATTService.fromBluetoothService( - device, selectedService); - final bluetoothRemoteGATTCharacteristic = BluetoothRemoteGATTCharacteristic( - service: bluetoothRemoteGATTService, - properties: - BluetoothCharacteristicProperties.fromCharacteristicProperties( - targetCharacteristic.properties), - uuid: targetCharacteristic.uuid.str, - value: null); - return bluetoothRemoteGATTCharacteristic.toMap(); - } - - BluetoothRemoteGATTCharacteristic getBluetoothRemoteGATTCharacteristic( - blue_plus.BluetoothCharacteristic selectedCharacteristic, - blue_plus.BluetoothService selectedService) { - final device = BluetoothDevice.getBluetoothDeviceFromScanResult( - state.selectedScanResult!); - final bluetoothRemoteGATTService = - BluetoothRemoteGATTService.fromBluetoothService( - device, selectedService); - final bluetoothRemoteGATTCharacteristic = BluetoothRemoteGATTCharacteristic( - service: bluetoothRemoteGATTService, - properties: - BluetoothCharacteristicProperties.fromCharacteristicProperties( - selectedCharacteristic.properties), - uuid: selectedCharacteristic.uuid.str, - value: null); - return bluetoothRemoteGATTCharacteristic; - } - - Future> - handleBluetoothRemoteGATTCharacteristicStartNotifications( - Map data) async { - collectLog( - 'handleBluetoothRemoteGATTCharacteristicStartNotifications : $data'); - final selectedService = await getSelectedService(data['serviceUUID']); - final selectedCharacteristic = - getSelectedCharacteristic(data['this'], selectedService); - - final bluetoothRemoteGATTCharacteristic = - getBluetoothRemoteGATTCharacteristic( - selectedCharacteristic, selectedService); - - initJSCharacteristicValueEmitter(selectedCharacteristic); - - return bluetoothRemoteGATTCharacteristic.toMap(); - } - - Future> - handleBluetoothRemoteGATTCharacteristicStopNotifications( - Map data) async { - collectLog( - 'handleBluetoothRemoteGATTCharacteristicStopNotifications : $data'); - final selectedService = await getSelectedService(data['serviceUUID']); - final selectedCharacteristic = - getSelectedCharacteristic(data['this'], selectedService); - - final bluetoothRemoteGATTCharacteristic = - getBluetoothRemoteGATTCharacteristic( - selectedCharacteristic, selectedService); - - removeJSCharacteristicValueEmitter(selectedCharacteristic); - - return bluetoothRemoteGATTCharacteristic.toMap(); - } - - Future> handleWrites(Map data, - {bool withResponse = true}) async { - collectLog('handleWrites : $data'); - final selectedService = await getSelectedService(data['serviceUUID']); - final selectedCharacteristic = - getSelectedCharacteristic(data['this'], selectedService); - final value = Uint8List.fromList(List.from( - (data['value'] as Map).values.toList())); - - collectLog('handleWrites:value $value'); - if (withResponse) { - await selectedCharacteristic.write(value); - } else { - await selectedCharacteristic.write(value, withoutResponse: true); - } - return {}; - } - - Future> - handleBluetoothRemoteGATTCharacteristicWriteValue( - Map data) async { - return handleWrites(data); - } - - Future> - handleBluetoothRemoteGATTCharacteristicWriteValueWithResponse( - Map data) async { - return handleWrites(data); - } - - Future> - handleBluetoothRemoteGATTCharacteristicWriteValueWithoutResponse( - Map data) async { - return handleWrites(data, withResponse: false); - } - - Future handleBluetoothRemoteGATTCharacteristicReadValue( - Map data) async { - collectLog('handleBluetoothRemoteGATTCharacteristicReadValue : $data'); - final selectedService = await getSelectedService(data['serviceUUID']); - final selectedCharacteristic = - getSelectedCharacteristic(data['this'], selectedService); - final value = selectedCharacteristic.lastValue; - - final uInt8List = Uint8List.fromList(value); - - collectLog('handleBluetoothRemoteGATTCharacteristicReadValue:value $value'); - collectLog( - 'handleBluetoothRemoteGATTCharacteristicReadValue:uInt8List ${uInt8List.toString()}'); - - return uInt8List; - } - - Timer? characteriticListnerTimer; - StreamSubscription>? characteristicValueStreamSubscription; + void injectAXSWalletJSChannel() => + JSChannelUtils.injectAXSWalletJSChannel(state); - void initJSCharacteristicValueEmitter( - blue_plus.BluetoothCharacteristic characteristic, - ) async { - await characteristic.setNotifyValue(true); - - characteristicValueStreamSubscription = - characteristic.lastValueStream.listen((event) async { - final uInt8List = Uint8List.fromList(event); - collectLog('characteristicValueStreamSubscription:event $event'); - collectLog( - 'characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}'); - final script = ''' - navigator.bluetooth.updateCharacteristicValue('${characteristic.uuid.str}', ${uInt8List.toString()},); - '''; - await state.webviewController!.evaluateJavascript(source: script); - }); - } - - void removeJSCharacteristicValueEmitter( - blue_plus.BluetoothCharacteristic characteristic, - ) async { - await characteristic.setNotifyValue(false); - - characteristicValueStreamSubscription?.cancel(); - } - - void injectAXSWalletJSChannel() async { - // Making It easy for accessing axs wallet - // use this way window.axs.callHandler - await state.webviewController!.evaluateJavascript( - source: JSChannelScripts.axsWalletObjectInjectScript( - JSChannelConfig.axsWalletJSObjectName)); - - await state.webviewController!.injectJavascriptFileFromAsset( - assetFilePath: 'assets/js/bluetooth/bluetooth.js'); - - // There is a gap for detecting the axs object in webview, It's intermittent after adding function structure to the scripts - Future.delayed( - const Duration(milliseconds: 500), - () async { - await state.webviewController!.evaluateJavascript( - source: JSChannelScripts.axsWalletReadyInjectScript( - JSChannelEvents.axsReadyEvent, - )); - }, - ); - } - - Future> jsChannelCronErrorHandler( - List args, - Future> Function( - Map, - AXSCronServices, - ) - callback, - ) async { - try { - Map channelDataMap; - - final channelData = args[0]; - channelDataMap = channelData as Map; - - final axsCronService = - AXSCronServicesExtension.getCronServiceFromJson(channelDataMap); - final callbackRes = await callback(channelDataMap, axsCronService); - return callbackRes; - } catch (e) { - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.failed, - data: null, - message: e.toString()); - return response.toMap((data) => {'message': e.toString()}); - } - } - - Future jsChannelErrorHandler( - List args, - Future Function( - Map, - ) - callback, - ) async { - try { - Map channelDataMap; - - final channelData = args[0]; - channelDataMap = channelData == null - ? {} - : channelData is String - ? json.decode(channelData) as Map - : channelData as Map; - - final callbackRes = await callback(channelDataMap); - return callbackRes; - } catch (e) { - if (e is BluetoothTimeoutError) { - addError(translate('unable_to_continue_bluetooth_is_turned_off')!); - } - - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.failed, - data: null, - message: e.toString()); - return response.toMap((data) => {'message': e}); - } - } - - // Update via functions & get data via steam & send the data via event eaach time - // ready => updateSystemInfo (service statues, mining service status, time, selected miners, camera permission location permission) - - Future> handleChangeCronTransition( - Map channelData, AXSCronServices axsCronService) async { - final axsCronService = - AXSCronServicesExtension.getCronServiceFromJson(channelData); - if (axsCronService == AXSCronServices.miningAutoClaimCron) { - ChangeCronTransitionRequestModel; - final changeCronTransitionRequestModel = - ChangeCronTransitionRequestModel.fromMap( - channelData['cron'], MiningCronServiceDataModel.fromMap); - - // Here i change the data that won't effect the - final currentDappHooksData = state.dappHooksData; - final newData = changeCronTransitionRequestModel.data; - - if (newData != null) { - final minersList = newData.minersList ?? - currentDappHooksData.minerHooks.selectedMiners; - _dAppHooksUseCase.updateMinersList(minersList); - - final newTimeOfDay = TimeOfDay.fromDateTime(newData.time!); - final currentTimeOfDay = - TimeOfDay.fromDateTime(currentDappHooksData.minerHooks.time); - - if (newData.time != null && newTimeOfDay != currentTimeOfDay) { - await minerHooksHelper.changeMinerHookTiming(newTimeOfDay); - } - } - - final miningCronServiceData = - MiningCronServiceDataModel.fromDAppHooksData( - _dAppHooksUseCase.dappHooksData.value); - - final responseData = CronServiceDataModel.fromDAppHooksData( - axsCronService, - _dAppHooksUseCase.dappHooksData.value, - miningCronServiceData); - - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.success, - data: responseData, - message: null); - return response.toMap(miningCronServiceData.toMapWrapper); - } else { - throw 'Unknown service'; - } - } - - Future> handleBluetoothRequestDevice( - Map channelData, - ) async { - // final options = RequestDeviceOptions.fromJson(channelData['data']); - final options = RequestDeviceOptions.fromMap(channelData); - late BluetoothDevice responseDevice; - - await _bluetoothUseCase.turnOnBluetoothAndProceed(); - - // Get the options data - _bluetoothUseCase.startScanning( - withServices: options.filters != null - ? options.filters! - .expand((filter) => filter.services ?? []) - .toList() - .firstOrNull - : [], - withRemoteIds: - null, // No direct mapping in RequestDeviceOptions, adjust as necessary - withNames: options.filters != null - ? options.filters! - .where((filter) => filter.name != null) - .map((filter) => filter.name!) - .toList() - : [], - withKeywords: options.filters != null - ? options.filters! - .where((filter) => filter.namePrefix != null) - .map((filter) => filter.namePrefix!) - .toList() - : [], - withMsd: options.filters != null - ? options.filters! - .expand((filter) => filter.manufacturerData ?? []) - .toList() - .firstOrNull - : [], - withServiceData: options.filters != null - ? options.filters! - .expand((filter) => filter.serviceData ?? []) - .toList() - .firstOrNull - : [], - continuousUpdates: true, - continuousDivisor: 2, - androidUsesFineLocation: true, - ); - - final blueberryRing = await getBlueberryRing(); - _bluetoothUseCase.stopScanner(); - if (blueberryRing == null) { - return {}; - } else { - responseDevice = blueberryRing; - } - - return responseDevice.toMap(); - } - - Future getBlueberryRing() async { - loading = true; - return Future.delayed(const Duration(seconds: 3), () async { - loading = false; - BluetoothDevice? responseDevice; - final scanResults = _bluetoothUseCase.scanResults.value; - if (scanResults.length == 1) { - // only one scan results - final scanResult = scanResults.first; - state.selectedScanResult = scanResult; - } else { - // We need to let the user to choose If two or more devices of rings are available and even If empty maybe let the user to wait - final scanResult = await showBlueberryRingsBottomSheet( - context!, - ); - if (scanResult != null) { - state.selectedScanResult = scanResult; - } - } - if (state.selectedScanResult != null) { - responseDevice = BluetoothDevice.getBluetoothDeviceFromScanResult( - state.selectedScanResult!); - } - - return responseDevice; - }); - } - - Future> handleChangeCronTransitionStatusEvent( - Map channelData, - AXSCronServices axsCronService, - ) async { - if (axsCronService == AXSCronServices.miningAutoClaimCron) { - final status = channelData['cron']['status']; - - await minerHooksHelper.changeMinerHooksEnabled(status); - final miningCronServiceData = - MiningCronServiceDataModel.fromDAppHooksData( - _dAppHooksUseCase.dappHooksData.value); - - final responseData = CronServiceDataModel.fromDAppHooksData( - axsCronService, - _dAppHooksUseCase.dappHooksData.value, - miningCronServiceData); - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.success, - message: null, - data: responseData); - return response.toMap(miningCronServiceData.toMapWrapper); - } else { - throw 'Unknown cron service'; - } - } - - Future> handleGetSystemInfoEvent( - Map channelData, - AXSCronServices axsCronService, - ) async { - if (axsCronService == AXSCronServices.miningAutoClaimCron) { - final dappHooksData = state.dappHooksData; - - final miningCronServiceData = - MiningCronServiceDataModel.fromDAppHooksData(dappHooksData); - - final responseData = CronServiceDataModel.fromDAppHooksData( - axsCronService, dappHooksData, miningCronServiceData); - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.success, - message: null, - data: responseData, - ); - return response.toMap(miningCronServiceData.toMapWrapper); - } else { - throw 'Unknown cron service'; - } - } - - Future> handleGoToAdvancedSettingsEvent( - Map channelData, AXSCronServices axsCronService) async { - goToAdvancedSettings(); - final response = AXSJSChannelResponseModel( - status: AXSJSChannelResponseStatus.success, message: null, data: null); - return response.toMap((data) => {}); - } - - void goToAdvancedSettings() { - navigator!.push(route( - const DAppHooksPage(), - )); - } + void cancelCharacteristicListenerTimer() => + characteristicListenerTimer?.cancel(); } diff --git a/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart new file mode 100644 index 00000000..05a9423b --- /dev/null +++ b/lib/features/settings/subfeatures/dapp_hooks/dapp_hooks.dart @@ -0,0 +1,6 @@ +export 'dapp_hooks_page.dart'; +export 'dapp_hooks_presenter.dart'; +export 'dapp_hooks_state.dart'; +export 'domain/domain.dart'; +export 'utils/utils.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/features/settings/subfeatures/dapp_hooks/domain/domain.dart b/lib/features/settings/subfeatures/dapp_hooks/domain/domain.dart new file mode 100644 index 00000000..434fd2b1 --- /dev/null +++ b/lib/features/settings/subfeatures/dapp_hooks/domain/domain.dart @@ -0,0 +1,2 @@ +export 'dapp_hooks_use_case.dart'; +export 'dapp_hooks_repository.dart'; diff --git a/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart b/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart index d49561ac..b4235b43 100644 --- a/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart +++ b/lib/features/settings/subfeatures/dapp_hooks/utils/utils.dart @@ -2,3 +2,4 @@ export 'miner_hooks_helper.dart'; export 'snack_bar_utils.dart'; export 'dapp_hooks_helper.dart'; export 'blueberry_ring_helper.dart'; +export 'wifi_hooks_helper.dart'; diff --git a/lib/features/settings/subfeatures/dapp_hooks/widgets/widget.dart b/lib/features/settings/subfeatures/dapp_hooks/widgets/widgets.dart similarity index 100% rename from lib/features/settings/subfeatures/dapp_hooks/widgets/widget.dart rename to lib/features/settings/subfeatures/dapp_hooks/widgets/widgets.dart From 1dd8307961fff0636bfd2ba7edf64722dd14c487 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 7 Aug 2024 11:35:34 +0330 Subject: [PATCH 36/45] fix: Call sign message --- .../subfeatures/open_dapp/open_dapp_page.dart | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart index e6ea06ca..56747240 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart @@ -125,8 +125,28 @@ class OpenAppPage extends HookConsumerWidget { url: url); break; case EIP1193.signMessage: + Map object = params["object"]; + presenter.signMessage( + object: object, + cancel: () { + controller?.cancel(id); + }, + success: (idHash) { + controller?.sendResult(idHash, id); + }, + ); break; case EIP1193.signPersonalMessage: + Map object = params["object"]; + presenter.signMessage( + object: object, + cancel: () { + controller?.cancel(id); + }, + success: (idHash) { + controller?.sendResult(idHash, id); + }, + ); break; case EIP1193.signTypedMessage: Map object = params["object"]; From 20c6688d334e30487dff1e61ab9b49d309d3ddab Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 7 Aug 2024 12:54:11 +0330 Subject: [PATCH 37/45] fix: update shared --- packages/shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared b/packages/shared index f949a958..f98f0c92 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit f949a95849bf50e688ccb0ca8e312eb598210317 +Subproject commit f98f0c92c2dbebde870c0fe5816fbc2c90d05251 From 1d6448084a391d50f44e4a84962170d817212953 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 7 Aug 2024 15:12:04 +0330 Subject: [PATCH 38/45] fix: update shared --- packages/shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared b/packages/shared index f949a958..f98f0c92 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit f949a95849bf50e688ccb0ca8e312eb598210317 +Subproject commit f98f0c92c2dbebde870c0fe5816fbc2c90d05251 From d67d463da2b3baea10c6c08681c6b34103bd7f37 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 7 Aug 2024 16:41:26 +0330 Subject: [PATCH 39/45] refactor: Wallet provider --- .../domain/helpers/bridge/bridge.dart | 2 + .../bridge/bridge_functions_helper.dart | 152 +++++ .../domain/helpers/bridge/bridge_helper.dart | 353 ++++++++++++ .../open_dapp/domain/helpers/helpers.dart | 1 + .../open_dapp/open_dapp_presenter.dart | 534 ++++-------------- 5 files changed, 608 insertions(+), 434 deletions(-) create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart create mode 100644 lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge.dart new file mode 100644 index 00000000..c0e0d640 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge.dart @@ -0,0 +1,2 @@ +export 'bridge_helper.dart'; +export 'bridge_functions_helper.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart new file mode 100644 index 00000000..779ca0de --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart @@ -0,0 +1,152 @@ +import 'dart:typed_data'; + +import 'package:datadashwallet/common/components/components.dart'; +import 'package:datadashwallet/features/common/common.dart'; +import 'package:datadashwallet/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_use_case.dart'; +import 'package:datadashwallet/features/settings/settings.dart'; +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; + +import '../../../open_dapp.dart'; + +class BridgeFunctionsHelper { + BridgeFunctionsHelper({ + required this.state, + required this.context, + required this.translate, + required this.navigator, + required this.customTokensUseCase, + required this.tokenContractUseCase, + required this.transactionHistoryUseCase, + required this.chainConfigurationUseCase, + required this.addError, + required this.loading, + }); + + OpenDAppState state; + TokenContractUseCase tokenContractUseCase; + CustomTokensUseCase customTokensUseCase; + TransactionsHistoryUseCase transactionHistoryUseCase; + ChainConfigurationUseCase chainConfigurationUseCase; + NavigatorState? navigator; + BuildContext? context; + String? Function(String) translate; + void Function(bool v) loading; + void Function(dynamic error, [StackTrace? stackTrace]) addError; + + Future estimatedFee( + String from, + String to, + EtherAmount? gasPrice, + Uint8List data, + BigInt? amountOfGas, + ) async { + loading(true); + try { + final gasFee = await tokenContractUseCase.estimateGasFeeForContractCall( + from: from, + to: to, + gasPrice: gasPrice, + data: data, + amountOfGas: amountOfGas); + loading(false); + + return gasFee; + } catch (e, s) { + addError(e, s); + } finally { + loading(false); + } + } + + Future sendTransaction(String to, EtherAmount amount, + Uint8List? data, TransactionGasEstimation? estimatedGasFee, String url, + {String? from}) async { + final res = await tokenContractUseCase.sendTransaction( + privateKey: state.account!.privateKey, + to: to, + from: from, + amount: amount, + data: data, + estimatedGasFee: estimatedGasFee); + if (!MXCChains.isMXCChains(state.network!.chainId)) { + recordTransaction(res); + } + + return res.hash; + } + + String? signMessage( + String hexData, + ) { + loading(true); + try { + final res = tokenContractUseCase.signMessage( + privateKey: state.account!.privateKey, message: hexData); + return res; + } catch (e, s) { + addError(e, s); + } finally { + loading(false); + } + } + + String? signTypedMessage( + String hexData, + ) { + loading(true); + try { + final res = tokenContractUseCase.signTypedMessage( + privateKey: state.account!.privateKey, data: hexData); + return res; + } catch (e, s) { + addError(e, s); + } finally { + loading(false); + } + } + + bool addAsset(Token token) { + loading(true); + try { + customTokensUseCase.addItem(token); + return true; + } catch (error, stackTrace) { + addError(error, stackTrace); + return false; + } finally { + loading(false); + } + } + + void recordTransaction(TransactionModel tx) { + final currentNetwork = state.network!; + final chainId = currentNetwork.chainId; + final token = Token( + chainId: currentNetwork.chainId, + logoUri: currentNetwork.logo, + name: currentNetwork.label ?? currentNetwork.web3RpcHttpUrl, + symbol: currentNetwork.symbol, + address: null, + ); + + tx = tx.copyWith(token: token); + + transactionHistoryUseCase.spyOnTransaction( + tx, + ); + transactionHistoryUseCase.updateItem( + tx, + ); + } + + Network? updateNetwork(Network network, int index) { + chainConfigurationUseCase.updateItem(network, index); + return network; + } + + Network? addNewNetwork(Network newNetwork) { + chainConfigurationUseCase.addItem(newNetwork); + return newNetwork; + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart new file mode 100644 index 00000000..47655bb5 --- /dev/null +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart @@ -0,0 +1,353 @@ +import 'dart:convert'; + +import 'package:datadashwallet/common/common.dart'; +import 'package:datadashwallet/core/src/providers/providers.dart'; +import 'package:datadashwallet/features/common/common.dart'; + +import 'package:flutter/material.dart'; +import 'package:mxc_logic/mxc_logic.dart'; +import 'package:web3_provider/web3_provider.dart'; + +import '../../../../../../settings/subfeatures/chain_configuration/domain/domain.dart'; +import '../../../open_dapp.dart'; + +class BridgeHelper { + BridgeHelper({ + required this.tokenContractUseCase, + required this.chainConfigurationUseCase, + required this.authUseCase, + required this.errorUseCase, + required this.bridgeFunctionsHelper, + required this.state, + required this.context, + required this.translate, + required this.addError, + required this.loading, + required this.notify, + required this.addMessage, + }); + + OpenDAppState state; + TokenContractUseCase tokenContractUseCase; + ChainConfigurationUseCase chainConfigurationUseCase; + AuthUseCase authUseCase; + ErrorUseCase errorUseCase; + BridgeFunctionsHelper bridgeFunctionsHelper; + BuildContext? context; + String? Function(String) translate; + void Function(bool v) loading; + void Function(dynamic error, [StackTrace? stackTrace]) addError; + void Function([void Function()? fun]) notify; + void Function(dynamic message) addMessage; + + void signTransaction({ + required BridgeParams bridge, + required VoidCallback cancel, + required Function(String idHaethClientsh) success, + required String url, + }) async { + final amountEther = EtherAmount.inWei(bridge.value ?? BigInt.zero); + final amount = amountEther.getValueInUnit(EtherUnit.ether).toString(); + final bridgeData = MXCType.hexToUint8List(bridge.data ?? ''); + EtherAmount? gasPrice; + double? gasFee; + TransactionGasEstimation? estimatedGasFee; + BigInt? amountOfGas; + + if (bridge.gasPrice != null) { + gasPrice = EtherAmount.fromBase10String(EtherUnit.wei, bridge.gasPrice!); + } + + if (bridge.gas != null) { + amountOfGas = BigInt.parse(bridge.gas.toString()); + gasPrice = gasPrice ?? await tokenContractUseCase.getGasPrice(); + final gasPriceDouble = + gasPrice.getValueInUnit(EtherUnit.ether).toDouble(); + gasFee = gasPriceDouble * amountOfGas.toDouble(); + + estimatedGasFee = TransactionGasEstimation( + gasPrice: gasPrice, gas: amountOfGas, gasFee: gasFee); + } else { + estimatedGasFee = await bridgeFunctionsHelper.estimatedFee( + bridge.from!, bridge.to!, gasPrice, bridgeData, amountOfGas); + + if (estimatedGasFee == null) { + cancel.call(); + return; + } + } + + String finalFee = + (estimatedGasFee.gasFee / Config.dappSectionFeeDivision).toString(); + final maxFeeDouble = estimatedGasFee.gasFee * Config.priority; + final maxFeeString = + (maxFeeDouble / Config.dappSectionFeeDivision).toString(); + final maxFee = + Validation.isExpoNumber(maxFeeString) ? '0.000' : maxFeeString; + + if (Validation.isExpoNumber(finalFee)) { + finalFee = '0.000'; + } + + final symbol = state.network!.symbol; + + try { + final result = await showTransactionDialog(context!, + title: translate('confirm_transaction')!, + amount: amount, + from: bridge.from!, + to: bridge.to!, + estimatedFee: finalFee, + maxFee: maxFee, + symbol: symbol); + + if (result != null && result) { + loading(true); + + final hash = await bridgeFunctionsHelper.sendTransaction( + bridge.to!, amountEther, bridgeData, estimatedGasFee, url, + from: bridge.from); + if (hash != null) success.call(hash); + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + callErrorHandler(e, s); + } finally { + loading(false); + } + } + + void switchEthereumChain(dynamic id, Map params) async { + final rawChainId = params["object"]["chainId"] as String; + final chainId = MXCFormatter.hexToDecimal(rawChainId); + final networks = chainConfigurationUseCase.networks.value; + final foundChainIdIndex = + networks.indexWhere((element) => element.chainId == chainId); + + if (foundChainIdIndex != -1) { + final foundNetwork = networks[foundChainIdIndex]; + final res = await showSwitchNetworkDialog(context!, + fromNetwork: state.network!.label ?? state.network!.web3RpcHttpUrl, + toNetwork: foundNetwork.label ?? foundNetwork.web3RpcHttpUrl, + onTap: () { + switchDefaultNetwork(id, foundNetwork, rawChainId); + }); + if (!(res ?? false)) { + cancelRequest(id); + } + } else { + addError(translate('network_not_found')); + final e = + DAppErrors.switchEthereumChainErrors.unRecognizedChain(rawChainId); + sendProviderError( + id, e['code'], MXCFormatter.escapeDoubleQuotes(e['message'])); + } + } + + void addEthereumChain(dynamic id, Map params) async { + final networkDetails = AddEthereumChain.fromMap(params["object"]); + + final rawChainId = networkDetails.chainId; + final chainId = MXCFormatter.hexToDecimal(rawChainId); + final networks = chainConfigurationUseCase.networks.value; + final foundChainIdIndex = + networks.indexWhere((element) => element.chainId == chainId); + // user can add a network again meaning It will override the old network + final alreadyExists = foundChainIdIndex != -1; + final alreadyEnabled = + alreadyExists ? networks[foundChainIdIndex].enabled : false; + + // Add network + final newNetwork = Network.fromAddEthereumChain(networkDetails, chainId); + + final res = await showAddNetworkDialog( + context!, + network: newNetwork, + approveFunction: (network) => alreadyExists + ? bridgeFunctionsHelper.updateNetwork(network, foundChainIdIndex) + : bridgeFunctionsHelper.addNewNetwork(network), + ); + + if (!(res ?? false)) { + cancelRequest(id); + } else { + if (!alreadyEnabled) { + final res = await showSwitchNetworkDialog(context!, + fromNetwork: state.network!.label ?? state.network!.web3RpcHttpUrl, + toNetwork: newNetwork.label ?? newNetwork.web3RpcHttpUrl, + onTap: () { + switchDefaultNetwork(id, newNetwork, rawChainId); + }); + if (!(res ?? false)) { + cancelRequest(id); + } + } + } + } + + /// This function is used for both sign message and sign personal message + void signMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async { + final hexData = object['data'] as String; + String message = MXCType.hexToString(hexData); + int chainId = state.network!.chainId; + String name = state.network!.symbol; + + try { + final result = await showSignMessageDialog( + context!, + title: translate('signature_request')!, + message: message, + networkName: '$name ($chainId)', + ); + + if (result != null && result) { + final hash = bridgeFunctionsHelper.signMessage( + hexData, + ); + if (hash != null) success.call(hash); + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + addError(e, s); + } + } + + void signTypedMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async { + String hexData = object['raw'] as String; + Map data = + jsonDecode(object['raw'] as String) as Map; + Map domain = data['domain'] as Map; + String primaryType = data['primaryType']; + int chainId = (domain['chainId']) as int; + String name = domain['name'] as String; + + try { + final result = await showTypedMessageDialog(context!, + title: translate('signature_request')!, + message: data['message'] as Map, + networkName: '$name ($chainId)', + primaryType: primaryType); + + if (result != null && result) { + final hash = bridgeFunctionsHelper.signTypedMessage( + hexData, + ); + if (hash != null) success.call(hash); + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + addError(e, s); + } + } + + void setAddress(dynamic id) { + if (state.account != null) { + final walletAddress = state.account!.address; + state.webviewController?.setAddress(walletAddress, id); + } + } + + void switchDefaultNetwork(int id, Network toNetwork, String rawChainId) { + // "{"id":1692336424091,"name":"switchEthereumChain","object":{"chainId":"0x66eed"},"network":"ethereum"}" + chainConfigurationUseCase.switchDefaultNetwork(toNetwork); + authUseCase.resetNetwork(toNetwork); + loadDataDashProviders(toNetwork); + notify(() => state.network = toNetwork); + + setChain(id); + } + + void addAsset(int id, Map data, + {required VoidCallback cancel, + required Function(String status) success}) async { + final watchAssetData = WatchAssetModel.fromMap(data); + String titleText = translate('add_x') + ?.replaceFirst('{0}', translate('token')?.toLowerCase() ?? '--') ?? + '--'; + + try { + final result = await showAddAssetDialog( + context!, + token: watchAssetData, + title: titleText, + ); + + if (result != null && result) { + final res = bridgeFunctionsHelper.addAsset(Token( + decimals: watchAssetData.decimals, + address: watchAssetData.contract, + symbol: watchAssetData.symbol, + chainId: state.network?.chainId)); + + if (res) { + success.call(res.toString()); + addMessage(translate('add_token_success_message')); + } else { + cancel.call(); + } + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + addError(e, s); + } + } + + void callErrorHandler(dynamic e, StackTrace s) { + final isHandled = errorUseCase.handleError( + context!, + e, + addError, + translate, + ); + if (!isHandled) { + addError(e, s); + } + } + + void setChain(int? id) { + state.webviewController + ?.setChain(getProviderConfig(), state.network!.chainId, id); + } + + void cancelRequest(int id) { + state.webviewController?.cancel(id); + } + + void checkCancel(bool? res, Function moveOn, int id) { + if (!(res ?? false)) { + cancelRequest(id); + } else { + moveOn(); + } + } + + void sendProviderError(int id, int code, String message) { + state.webviewController?.sendProviderError(id, code, message); + } + + void sendError(String error, int id) { + state.webviewController + ?.sendError(MXCFormatter.escapeDoubleQuotes(error), id); + } + + String getProviderConfig() { + return JSChannelScripts.walletProviderInfoScript(state.network!.chainId, + state.network!.web3RpcHttpUrl, state.account!.address); + } +} diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart index 8d683965..4ad096da 100644 --- a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/helpers.dart @@ -1 +1,2 @@ export 'js_channels/js_channel.dart'; +export 'bridge/bridge.dart'; diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 4195c02b..16bc5187 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -96,6 +96,34 @@ class OpenDAppPresenter extends CompletePresenter { state: state, ); + BridgeFunctionsHelper get bridgeFunctionsHelper => BridgeFunctionsHelper( + translate: translate, + context: context, + state: state, + addError: addError, + chainConfigurationUseCase: _chainConfigurationUseCase, + tokenContractUseCase: _tokenContractUseCase, + transactionHistoryUseCase: _transactionHistoryUseCase, + customTokensUseCase: _customTokensUseCase, + loading: (bool value) => loading = value, + navigator: navigator, + ); + + BridgeHelper get bridgeHelper => BridgeHelper( + translate: translate, + context: context, + state: state, + addError: addError, + addMessage: addMessage, + authUseCase: _authUseCase, + chainConfigurationUseCase: _chainConfigurationUseCase, + errorUseCase: _errorUseCase, + tokenContractUseCase: _tokenContractUseCase, + bridgeFunctionsHelper: bridgeFunctionsHelper, + loading: (bool value) => loading = value, + notify: notify, + ); + @override void initState() { super.initState(); @@ -167,402 +195,8 @@ class OpenDAppPresenter extends CompletePresenter { ); } - Future _estimatedFee( - String from, - String to, - EtherAmount? gasPrice, - Uint8List data, - BigInt? amountOfGas, - ) async { - loading = true; - try { - final gasFee = await _tokenContractUseCase.estimateGasFeeForContractCall( - from: from, - to: to, - gasPrice: gasPrice, - data: data, - amountOfGas: amountOfGas); - loading = false; - - return gasFee; - } catch (e, s) { - addError(e, s); - } finally { - loading = false; - } - } - - Future _sendTransaction(String to, EtherAmount amount, - Uint8List? data, TransactionGasEstimation? estimatedGasFee, String url, - {String? from}) async { - final res = await _tokenContractUseCase.sendTransaction( - privateKey: state.account!.privateKey, - to: to, - from: from, - amount: amount, - data: data, - estimatedGasFee: estimatedGasFee); - if (!MXCChains.isMXCChains(state.network!.chainId)) { - recordTransaction(res); - } - - return res.hash; - } - - String? _signMessage( - String hexData, - ) { - loading = true; - try { - final res = _tokenContractUseCase.signMessage( - privateKey: state.account!.privateKey, message: hexData); - return res; - } catch (e, s) { - addError(e, s); - } finally { - loading = false; - } - } - - String? _signTypedMessage( - String hexData, - ) { - loading = true; - try { - final res = _tokenContractUseCase.signTypedMessage( - privateKey: state.account!.privateKey, data: hexData); - return res; - } catch (e, s) { - addError(e, s); - } finally { - loading = false; - } - } - - bool _addAsset(Token token) { - loading = true; - try { - _customTokensUseCase.addItem(token); - return true; - } catch (error, stackTrace) { - addError(error, stackTrace); - return false; - } finally { - loading = false; - } - } - - void recordTransaction(TransactionModel tx) { - final currentNetwork = state.network!; - final chainId = currentNetwork.chainId; - final token = Token( - chainId: currentNetwork.chainId, - logoUri: currentNetwork.logo, - name: currentNetwork.label ?? currentNetwork.web3RpcHttpUrl, - symbol: currentNetwork.symbol, - address: null, - ); - - tx = tx.copyWith(token: token); - - _transactionHistoryUseCase.spyOnTransaction( - tx, - ); - _transactionHistoryUseCase.updateItem( - tx, - ); - } - - void signTransaction({ - required BridgeParams bridge, - required VoidCallback cancel, - required Function(String idHaethClientsh) success, - required String url, - }) async { - final amountEther = EtherAmount.inWei(bridge.value ?? BigInt.zero); - final amount = amountEther.getValueInUnit(EtherUnit.ether).toString(); - final bridgeData = MXCType.hexToUint8List(bridge.data ?? ''); - EtherAmount? gasPrice; - double? gasFee; - TransactionGasEstimation? estimatedGasFee; - BigInt? amountOfGas; - - if (bridge.gasPrice != null) { - gasPrice = EtherAmount.fromBase10String(EtherUnit.wei, bridge.gasPrice!); - } - - if (bridge.gas != null) { - amountOfGas = BigInt.parse(bridge.gas.toString()); - gasPrice = gasPrice ?? await _tokenContractUseCase.getGasPrice(); - final gasPriceDouble = - gasPrice.getValueInUnit(EtherUnit.ether).toDouble(); - gasFee = gasPriceDouble * amountOfGas.toDouble(); - - estimatedGasFee = TransactionGasEstimation( - gasPrice: gasPrice, gas: amountOfGas, gasFee: gasFee); - } else { - estimatedGasFee = await _estimatedFee( - bridge.from!, bridge.to!, gasPrice, bridgeData, amountOfGas); - - if (estimatedGasFee == null) { - cancel.call(); - return; - } - } - - String finalFee = - (estimatedGasFee.gasFee / Config.dappSectionFeeDivision).toString(); - final maxFeeDouble = estimatedGasFee.gasFee * Config.priority; - final maxFeeString = - (maxFeeDouble / Config.dappSectionFeeDivision).toString(); - final maxFee = - Validation.isExpoNumber(maxFeeString) ? '0.000' : maxFeeString; - - if (Validation.isExpoNumber(finalFee)) { - finalFee = '0.000'; - } - - final symbol = state.network!.symbol; - - try { - final result = await showTransactionDialog(context!, - title: translate('confirm_transaction')!, - amount: amount, - from: bridge.from!, - to: bridge.to!, - estimatedFee: finalFee, - maxFee: maxFee, - symbol: symbol); - - if (result != null && result) { - loading = true; - - final hash = await _sendTransaction( - bridge.to!, amountEther, bridgeData, estimatedGasFee, url, - from: bridge.from); - if (hash != null) success.call(hash); - } else { - cancel.call(); - } - } catch (e, s) { - cancel.call(); - callErrorHandler(e, s); - } finally { - loading = false; - } - } - - void callErrorHandler(dynamic e, StackTrace s) { - final isHandled = _errorUseCase.handleError( - context!, - e, - addError, - translate, - ); - if (!isHandled) { - addError(e, s); - } - } - - void switchEthereumChain(dynamic id, Map params) async { - final rawChainId = params["object"]["chainId"] as String; - final chainId = MXCFormatter.hexToDecimal(rawChainId); - final networks = _chainConfigurationUseCase.networks.value; - final foundChainIdIndex = - networks.indexWhere((element) => element.chainId == chainId); - - if (foundChainIdIndex != -1) { - final foundNetwork = networks[foundChainIdIndex]; - final res = await showSwitchNetworkDialog(context!, - fromNetwork: state.network!.label ?? state.network!.web3RpcHttpUrl, - toNetwork: foundNetwork.label ?? foundNetwork.web3RpcHttpUrl, - onTap: () { - switchDefaultNetwork(id, foundNetwork, rawChainId); - }); - if (!(res ?? false)) { - cancelRequest(id); - } - } else { - addError(translate('network_not_found')); - final e = - DAppErrors.switchEthereumChainErrors.unRecognizedChain(rawChainId); - sendProviderError( - id, e['code'], MXCFormatter.escapeDoubleQuotes(e['message'])); - } - } - - void checkCancel(bool? res, Function moveOn, int id) { - if (!(res ?? false)) { - cancelRequest(id); - } else { - moveOn(); - } - } - - void sendProviderError(int id, int code, String message) { - state.webviewController?.sendProviderError(id, code, message); - } - - void sendError(String error, int id) { - state.webviewController - ?.sendError(MXCFormatter.escapeDoubleQuotes(error), id); - } - - void cancelRequest(int id) { - state.webviewController?.cancel(id); - } - - void unSupportedRequest() { - addError(translate('network_not_found')); - } - - void addEthereumChain(dynamic id, Map params) async { - final networkDetails = AddEthereumChain.fromMap(params["object"]); - - final rawChainId = networkDetails.chainId; - final chainId = MXCFormatter.hexToDecimal(rawChainId); - final networks = _chainConfigurationUseCase.networks.value; - final foundChainIdIndex = - networks.indexWhere((element) => element.chainId == chainId); - // user can add a network again meaning It will override the old network - final alreadyExists = foundChainIdIndex != -1; - final alreadyEnabled = - alreadyExists ? networks[foundChainIdIndex].enabled : false; - - // Add network - final newNetwork = Network.fromAddEthereumChain(networkDetails, chainId); - - final res = await showAddNetworkDialog( - context!, - network: newNetwork, - approveFunction: (network) => alreadyExists - ? updateNetwork(network, foundChainIdIndex) - : addNewNetwork(network), - ); - - if (!(res ?? false)) { - cancelRequest(id); - } else { - if (!alreadyEnabled) { - final res = await showSwitchNetworkDialog(context!, - fromNetwork: state.network!.label ?? state.network!.web3RpcHttpUrl, - toNetwork: newNetwork.label ?? newNetwork.web3RpcHttpUrl, - onTap: () { - switchDefaultNetwork(id, newNetwork, rawChainId); - }); - if (!(res ?? false)) { - cancelRequest(id); - } - } - } - } - - Network? updateNetwork(Network network, int index) { - _chainConfigurationUseCase.updateItem(network, index); - return network; - } - - Network? addNewNetwork(Network newNetwork) { - _chainConfigurationUseCase.addItem(newNetwork); - return newNetwork; - } - - /// This function is used for both sign message and sign personal message - void signMessage({ - required Map object, - required VoidCallback cancel, - required Function(String hash) success, - }) async { - final hexData = object['data'] as String; - String message = MXCType.hexToString(hexData); - int chainId = state.network!.chainId; - String name = state.network!.symbol; - - try { - final result = await showSignMessageDialog( - context!, - title: translate('signature_request')!, - message: message, - networkName: '$name ($chainId)', - ); - - if (result != null && result) { - final hash = _signMessage( - hexData, - ); - if (hash != null) success.call(hash); - } else { - cancel.call(); - } - } catch (e, s) { - cancel.call(); - addError(e, s); - } - } - - void signTypedMessage({ - required Map object, - required VoidCallback cancel, - required Function(String hash) success, - }) async { - String hexData = object['raw'] as String; - Map data = - jsonDecode(object['raw'] as String) as Map; - Map domain = data['domain'] as Map; - String primaryType = data['primaryType']; - int chainId = (domain['chainId']) as int; - String name = domain['name'] as String; - - try { - final result = await showTypedMessageDialog(context!, - title: translate('signature_request')!, - message: data['message'] as Map, - networkName: '$name ($chainId)', - primaryType: primaryType); - - if (result != null && result) { - final hash = _signTypedMessage( - hexData, - ); - if (hash != null) success.call(hash); - } else { - cancel.call(); - } - } catch (e, s) { - cancel.call(); - addError(e, s); - } - } - void changeProgress(int progress) => notify(() => state.progress = progress); - void setAddress(dynamic id) { - if (state.account != null) { - final walletAddress = state.account!.address; - state.webviewController?.setAddress(walletAddress, id); - } - } - - void switchDefaultNetwork(int id, Network toNetwork, String rawChainId) { - // "{"id":1692336424091,"name":"switchEthereumChain","object":{"chainId":"0x66eed"},"network":"ethereum"}" - _chainConfigurationUseCase.switchDefaultNetwork(toNetwork); - _authUseCase.resetNetwork(toNetwork); - loadDataDashProviders(toNetwork); - notify(() => state.network = toNetwork); - - setChain(id); - } - - void setChain(int? id) { - state.webviewController - ?.setChain(getProviderConfig(), state.network!.chainId, id); - } - - String getProviderConfig() { - return JSChannelScripts.walletProviderInfoScript(state.network!.chainId, - state.network!.web3RpcHttpUrl, state.account!.address); - } - void copy(List params) { Clipboard.setData(ClipboardData(text: params[0])); } @@ -586,43 +220,6 @@ class OpenDAppPresenter extends CompletePresenter { return Validation.isAddress(address); } - void addAsset(int id, Map data, - {required VoidCallback cancel, - required Function(String status) success}) async { - final watchAssetData = WatchAssetModel.fromMap(data); - String titleText = translate('add_x') - ?.replaceFirst('{0}', translate('token')?.toLowerCase() ?? '--') ?? - '--'; - - try { - final result = await showAddAssetDialog( - context!, - token: watchAssetData, - title: titleText, - ); - - if (result != null && result) { - final res = _addAsset(Token( - decimals: watchAssetData.decimals, - address: watchAssetData.contract, - symbol: watchAssetData.symbol, - chainId: state.network?.chainId)); - - if (res) { - success.call(res.toString()); - addMessage(translate('add_token_success_message')); - } else { - cancel.call(); - } - } else { - cancel.call(); - } - } catch (e, s) { - cancel.call(); - addError(e, s); - } - } - void launchAddress(String address) { _launcherUseCase.viewAddress(address); } @@ -663,6 +260,76 @@ class OpenDAppPresenter extends CompletePresenter { void hidePanel() => PanelUtils.hidePanel(state, panelTimer); + void signTransaction({ + required BridgeParams bridge, + required VoidCallback cancel, + required Function(String idHaethClientsh) success, + required String url, + }) async => + bridgeHelper.signTransaction( + bridge: bridge, + cancel: cancel, + success: success, + url: url, + ); + + void switchEthereumChain(dynamic id, Map params) async => + bridgeHelper.switchEthereumChain( + id, + params, + ); + + void addEthereumChain(dynamic id, Map params) async => + bridgeHelper.addEthereumChain( + id, + params, + ); + + void signMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async => + bridgeHelper.signMessage( + object: object, + cancel: cancel, + success: success, + ); + + void signTypedMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async => + bridgeHelper.signTypedMessage( + object: object, + cancel: cancel, + success: success, + ); + + void setAddress(dynamic id) => bridgeHelper.setAddress( + id, + ); + + void switchDefaultNetwork(int id, Network toNetwork, String rawChainId) => + bridgeHelper.switchDefaultNetwork( + id, + toNetwork, + rawChainId, + ); + + void addAsset(int id, Map data, + {required VoidCallback cancel, + required Function(String status) success}) async => + bridgeHelper.addAsset( + id, + data, + cancel: cancel, + success: success, + ); + + void setChain(int? id) => bridgeHelper.setChain(id); + void closedApp() { navigator!.pop(); } @@ -690,9 +357,8 @@ class OpenDAppPresenter extends CompletePresenter { } } - void changeOnLoadStopCalled() { - state.isLoadStopCalled = !state.isLoadStopCalled; - } + void changeOnLoadStopCalled() => + state.isLoadStopCalled = !state.isLoadStopCalled; void injectAXSWalletJSChannel() => JSChannelUtils.injectAXSWalletJSChannel(state); From d77a9f054f0e3bcf6202c07545dbf296bdfc4cfc Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 8 Aug 2024 15:14:47 +0330 Subject: [PATCH 40/45] feat: Add sign personal message --- .../contract/token_contract_use_case.dart | 6 ++++ .../bridge/bridge_functions_helper.dart | 15 ++++++++ .../domain/helpers/bridge/bridge_helper.dart | 35 ++++++++++++++++++- .../subfeatures/open_dapp/open_dapp_page.dart | 7 ++-- .../open_dapp/open_dapp_presenter.dart | 11 ++++++ packages/shared | 2 +- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/lib/features/common/contract/token_contract_use_case.dart b/lib/features/common/contract/token_contract_use_case.dart index 16b98567..283723ca 100644 --- a/lib/features/common/contract/token_contract_use_case.dart +++ b/lib/features/common/contract/token_contract_use_case.dart @@ -269,6 +269,12 @@ class TokenContractUseCase extends ReactiveUseCase { .getTokenTransferData(tokenHash, toAddress, amount); } + String signPersonalMessage({required String privateKey, required String message}) { + return _repository.tokenContract + .signPersonalMessage(privateKey: privateKey, message: message); + } + + String signMessage({required String privateKey, required String message}) { return _repository.tokenContract .signMessage(privateKey: privateKey, message: message); diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart index 779ca0de..d010bf28 100644 --- a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_functions_helper.dart @@ -91,6 +91,21 @@ class BridgeFunctionsHelper { } } + String? signPersonalMessage( + String hexData, + ) { + loading(true); + try { + final res = tokenContractUseCase.signPersonalMessage( + privateKey: state.account!.privateKey, message: hexData); + return res; + } catch (e, s) { + addError(e, s); + } finally { + loading(false); + } + } + String? signTypedMessage( String hexData, ) { diff --git a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart index 47655bb5..a9aa07e3 100644 --- a/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart +++ b/lib/features/dapps/subfeatures/open_dapp/domain/helpers/bridge/bridge_helper.dart @@ -187,7 +187,7 @@ class BridgeHelper { } } - /// This function is used for both sign message and sign personal message + void signMessage({ required Map object, required VoidCallback cancel, @@ -220,6 +220,39 @@ class BridgeHelper { } } + + void signPersonalMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async { + final hexData = object['data'] as String; + String message = MXCType.hexToString(hexData); + int chainId = state.network!.chainId; + String name = state.network!.symbol; + + try { + final result = await showSignMessageDialog( + context!, + title: translate('signature_request')!, + message: message, + networkName: '$name ($chainId)', + ); + + if (result != null && result) { + final hash = bridgeFunctionsHelper.signPersonalMessage( + hexData, + ); + if (hash != null) success.call(hash); + } else { + cancel.call(); + } + } catch (e, s) { + cancel.call(); + addError(e, s); + } + } + void signTypedMessage({ required Map object, required VoidCallback cancel, diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart index 56747240..a73f60fa 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_page.dart @@ -100,8 +100,7 @@ class OpenAppPage extends HookConsumerWidget { presenter.changeProgress(progress); presenter.setChain(null); }, - onUpdateVisitedHistory: - (controller, url, androidIsReload) { + onUpdateVisitedHistory: (controller, url, androidIsReload) { presenter.updateCurrentUrl(url); }, shouldOverrideUrlLoading: presenter.checkDeepLink, @@ -137,8 +136,8 @@ class OpenAppPage extends HookConsumerWidget { ); break; case EIP1193.signPersonalMessage: - Map object = params["object"]; - presenter.signMessage( + Map object = params["object"]; + presenter.signPersonalMessage( object: object, cancel: () { controller?.cancel(id); diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 16bc5187..fb12a4fe 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -296,6 +296,17 @@ class OpenDAppPresenter extends CompletePresenter { success: success, ); + void signPersonalMessage({ + required Map object, + required VoidCallback cancel, + required Function(String hash) success, + }) async => + bridgeHelper.signPersonalMessage( + object: object, + cancel: cancel, + success: success, + ); + void signTypedMessage({ required Map object, required VoidCallback cancel, diff --git a/packages/shared b/packages/shared index f98f0c92..5cbb0d14 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit f98f0c92c2dbebde870c0fe5816fbc2c90d05251 +Subproject commit 5cbb0d141c97876ec2afa7994952f0896c0b2284 From ac0f580ca7e366980acb436c8da12e4a9284e0b3 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 15 Aug 2024 12:48:51 +0330 Subject: [PATCH 41/45] fix: Navigation bug on pass code change --- .../passcode_change_confirm_page_presenter.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/features/security/presentation/passcode_change/passcode_change_confirm_page/passcode_change_confirm_page_presenter.dart b/lib/features/security/presentation/passcode_change/passcode_change_confirm_page/passcode_change_confirm_page_presenter.dart index 083f73d3..8aa2df0e 100644 --- a/lib/features/security/presentation/passcode_change/passcode_change_confirm_page/passcode_change_confirm_page_presenter.dart +++ b/lib/features/security/presentation/passcode_change/passcode_change_confirm_page/passcode_change_confirm_page_presenter.dart @@ -31,6 +31,8 @@ class PasscodeChangeConfirmPagePresenter extends PasscodeBasePagePresenter { _passcodeUseCase.setNeedSetPasscode(false); _passcodeUseCase.setPasscode(expectedNumbers.join()); - navigator?.popFeature(); + navigator?.popUntil((route) { + return route.settings.name?.contains('SecuritySettingsPage') ?? false; + }); } } From 565073a2d1e9eb870382c9f4f1f550de2c825c60 Mon Sep 17 00:00:00 2001 From: reasje Date: Thu, 15 Aug 2024 16:01:39 +0330 Subject: [PATCH 42/45] fix: Text alignment --- lib/common/components/list/single_line_info_item.dart | 2 +- .../dapps/subfeatures/open_dapp/widgets/message_info.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common/components/list/single_line_info_item.dart b/lib/common/components/list/single_line_info_item.dart index 9b2b7759..0b9f6b29 100644 --- a/lib/common/components/list/single_line_info_item.dart +++ b/lib/common/components/list/single_line_info_item.dart @@ -49,7 +49,7 @@ class SingleLineInfoItem extends HookConsumerWidget { value, style: FontTheme.of(context).body1.primary(), softWrap: true, - textAlign: TextAlign.end, + textAlign: TextAlign.start, ), ), if (valueActionIcon != null) diff --git a/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart b/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart index efac3123..5e48a36d 100644 --- a/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart +++ b/lib/features/dapps/subfeatures/open_dapp/widgets/message_info.dart @@ -58,7 +58,7 @@ class MessageInfo extends ConsumerWidget { return Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, children: [ Text( networkName, From 7d1b7b8e7e25cec5ba2c0a1ebf0239fe8cf98189 Mon Sep 17 00:00:00 2001 From: HU Xin Date: Fri, 16 Aug 2024 09:00:49 +0200 Subject: [PATCH 43/45] translate: new --- assets/flutter_i18n/de.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/es.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/fr.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/id.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/it.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/ja.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/ko.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/nl.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/pt.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/ro.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/ru.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/tr.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/vi.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/zh_CN.json | 38 +++++++++++++++++++++++++++++++++- assets/flutter_i18n/zh_TW.json | 38 +++++++++++++++++++++++++++++++++- 15 files changed, 555 insertions(+), 15 deletions(-) diff --git a/assets/flutter_i18n/de.json b/assets/flutter_i18n/de.json index a03b4a0c..c01a8577 100644 --- a/assets/flutter_i18n/de.json +++ b/assets/flutter_i18n/de.json @@ -417,5 +417,41 @@ "save_locally": "Lokal speichern", "save_locally_description": "Stellen Sie sicher, dass Sie Ihre Schlüssel lokal speichern und dann können Sie loslegen.", "axs_storage_permission_use_case": "Die AXS Wallet benötigt Zugriff auf Ihren Speicher für Funktionen wie RWA. Ihre Speicherdaten werden nicht gespeichert oder mit Dritten geteilt.", - "local_backup": "Lokale Sicherung" + "local_backup": "Lokale Sicherung", + "no_description": "Keine Beschreibung", + "bluetooth_not_supported": "Bluetooth wird auf diesem Gerät nicht unterstützt.", + "blueberry_ring_hooks": "Blaubeere Ring Haken", + "nearby_blueberry_rings": "In der Nähe von Blaubeer-Ringen", + "unable_to_continue_bluetooth_is_turned_off": "Kann nicht fortsetzen, Bluetooth ist ausgeschaltet!", + "scanning": "Scannen ...", + "blueberry_ring_inactive_alert_title": "Zeit für einen Spaziergang!", + "blueberry_ring_inactive_alert_text": "Sie waren eine Weile inaktiv. Ein kurzer Spaziergang könnte wirklich belebend sein!", + "blueberry_ring_sleep_alert_title": "Sie haben in letzter Zeit weniger Tiefschlaf bekommen als üblich. Versuchen Sie, sich heute Abend 30 Minuten früher zu entspannen, um besser auszuruhen.", + "blueberry_ring_sleep_alert_text": "Sie haben in letzter Zeit weniger Tiefschlaf bekommen als üblich. Versuchen Sie, sich heute Abend 30 Minuten früher zu entspannen, um besser auszuruhen.", + "blueberry_ring_heart_rate_alert_title": "Ihre Herzfrequenz war heute ungewöhnlich hoch. Wenn Sie sich unwohl fühlen, könnte es gut sein, einen Arzt aufzusuchen.", + "blueberry_ring_heart_rate_alert_text": "Ihre Herzfrequenz war heute ungewöhnlich hoch. Wenn Sie sich unwohl fühlen, könnte es gut sein, einen Arzt aufzusuchen.", + "blueberry_ring_battery_alert_title": "Der Akku ist fast leer!", + "blueberry_ring_battery_alert_text": "Der Akku Ihres Blueberry Rings ist fast leer. Bitte laden Sie ihn bald auf, um Datenlücken zu vermeiden.", + "activity_reminder": "Aktivitätserinnerung", + "sleep_insight": "Schlaf Einblick", + "heart_alert": "Herzalarm", + "low_battery": "Niedriger Akkustand", + "blueberry_background_notifications_requirements_title": "Dieser Service erfordert:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth soll EINGESCHALTET sein", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry soll erreichbar sein", + "auto_sync_started": "Blueberry Ring Autosynchronisation gestartet 🏁", + "no_rings_selected_notification_title": "Sieht so aus, als hätten Sie keine Blueberry Rings ausgewählt. ℹ️", + "no_rings_selected_notification_text": "Bitte gehen Sie zur Blueberry Ring DApp, um Ringe auszuwählen.", + "auto_sync_successful_notification_title": "Erfolgreiche Auto-Claim von Blueberry Ring ✅", + "auto_sync_successful_notification_text": "Ihre Ringdaten wurden erfolgreich mit der AXS-Wallet synchronisiert.", + "already_synced_notification_title": "Hoppla, bereits synchronisiert ℹ️", + "already_synced_notification_text": "Die AXS-Wallet hat versucht, Ihre Ringdaten zu synchronisieren, aber es sieht so aus, als hätten Sie die Ringdaten heute bereits synchronisiert.", + "auto_sync_failed": "Blueberry Ring Auto-Sync fehlgeschlagen ❌", + "no_rings_owned_notification": "Sieht so aus, als ob diese Wallet keine Blueberry Rings besitzt. ℹ️", + "syncing_data_from_ring": "Synchronisieren von Daten aus dem Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Blaubeere Ring #{0}: Bereits synchronisiert. ℹ️", + "data_synced_successfully_ring": "Blaubeere Ring #{0}: Daten erfolgreich synchronisiert. ✅", + "data_syncing_failed": "Blaubeere Ring #{0}: Daten-Synchronisationsprozess fehlgeschlagen. ❌", + "blueberry_hooks": "Blaubeerhaken", + "message": "Nachricht" } \ No newline at end of file diff --git a/assets/flutter_i18n/es.json b/assets/flutter_i18n/es.json index 64d48fff..215ffc05 100644 --- a/assets/flutter_i18n/es.json +++ b/assets/flutter_i18n/es.json @@ -417,5 +417,41 @@ "save_locally": "Guardar localmente", "save_locally_description": "Asegúrate de guardar tus claves localmente y luego estás listo para continuar.", "axs_storage_permission_use_case": "La billetera AXS necesita acceso a tu almacenamiento para funciones como RWA. Tus datos de almacenamiento no se guardan ni se comparten con terceros.", - "local_backup": "Copia de seguridad local" + "local_backup": "Copia de seguridad local", + "no_description": "Sin descripción", + "bluetooth_not_supported": "Bluetooth no es compatible con este dispositivo.", + "blueberry_ring_hooks": "Blueberry Ring se engancha", + "nearby_blueberry_rings": "Anillos de Arándano Cercanos", + "unable_to_continue_bluetooth_is_turned_off": "No se puede continuar, ¡el Bluetooth está apagado!", + "scanning": "Escaneando ...", + "blueberry_ring_inactive_alert_title": "¡Hora de ir a dar un paseo!", + "blueberry_ring_inactive_alert_text": "Has estado inactivo durante un tiempo. ¡Un corto paseo podría ser realmente vigorizante!", + "blueberry_ring_sleep_alert_title": "Has estado obteniendo menos sueño profundo de lo habitual. Intenta relajarte 30 minutos antes esta noche para un mejor descanso.", + "blueberry_ring_sleep_alert_text": "Has estado obteniendo menos sueño profundo de lo habitual. Intenta relajarte 30 minutos antes esta noche para descansar mejor.", + "blueberry_ring_heart_rate_alert_title": "Tu ritmo cardíaco ha estado inusualmente alto hoy. Si te sientes mal, podría ser bueno consultar con un médico.", + "blueberry_ring_heart_rate_alert_text": "Tu ritmo cardíaco ha estado inusualmente alto hoy. Si te sientes mal, podría ser bueno consultar con un médico.", + "blueberry_ring_battery_alert_title": "¡La batería está baja!", + "blueberry_ring_battery_alert_text": "La batería de tu Anillo Blueberry está baja. Por favor, cárgala pronto para evitar interrupciones en los datos.", + "activity_reminder": "Recordatorio de actividad", + "sleep_insight": "Perspectiva del sueño", + "heart_alert": "Alerta de corazón", + "low_battery": "Batería baja", + "blueberry_background_notifications_requirements_title": "Este servicio requiere:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth debe estar ENCENDIDO", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry para ser accesible", + "auto_sync_started": "El auto sincronización de Blueberry Ring ha comenzado 🏁", + "no_rings_selected_notification_title": "Parece que no has seleccionado ningún Anillo de Arándano. ℹ️", + "no_rings_selected_notification_text": "Por favor, dirígete a la DApp de Blueberry Ring para seleccionar anillos.", + "auto_sync_successful_notification_title": "El auto-reclamo de Blueberry Ring ha sido exitoso ✅", + "auto_sync_successful_notification_text": "La cartera AXS ha sincronizado con éxito tus datos de anillo.", + "already_synced_notification_title": "Ups, ya sincronizado ℹ️", + "already_synced_notification_text": "La cartera AXS intentó sincronizar tus datos de anillo, pero parece que ya has sincronizado los datos del anillo hoy.", + "auto_sync_failed": "Falló la sincronización automática de Blueberry Ring ❌", + "no_rings_owned_notification": "Parece que esta billetera no posee ningún Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Sincronizando datos desde Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Anillo de Arándano #{0}: Ya sincronizado. ℹ️", + "data_synced_successfully_ring": "Anillo de Arándano #{0}: Datos sincronizados con éxito. ✅", + "data_syncing_failed": "Anillo de Arándano #{0}: El proceso de sincronización de datos ha fallado. ❌", + "blueberry_hooks": "Ganchos de Arándano", + "message": "Mensaje" } \ No newline at end of file diff --git a/assets/flutter_i18n/fr.json b/assets/flutter_i18n/fr.json index 6f7a6d6c..4a6f6bd6 100644 --- a/assets/flutter_i18n/fr.json +++ b/assets/flutter_i18n/fr.json @@ -417,5 +417,41 @@ "save_locally": "Enregistrez localement", "save_locally_description": "Assurez-vous de sauvegarder vos clés localement et ensuite vous êtes prêt à partir.", "axs_storage_permission_use_case": "Le portefeuille AXS a besoin d'accéder à votre stockage pour des fonctionnalités telles que RWA. Vos données de stockage ne sont pas sauvegardées ni partagées avec des tiers.", - "local_backup": "Sauvegarde locale" + "local_backup": "Sauvegarde locale", + "no_description": "Aucune description", + "bluetooth_not_supported": "Le Bluetooth n'est pas pris en charge sur cet appareil.", + "blueberry_ring_hooks": "Les Crochets de l'Anneau de Myrtille", + "nearby_blueberry_rings": "Anneaux de myrtille à proximité", + "unable_to_continue_bluetooth_is_turned_off": "Impossible de continuer, le Bluetooth est éteint!", + "scanning": "Analyse en cours...", + "blueberry_ring_inactive_alert_title": "Il est temps d'aller se promener!", + "blueberry_ring_inactive_alert_text": "Vous avez été inactif pendant un moment. Une petite promenade pourrait être vraiment revigorante!", + "blueberry_ring_sleep_alert_title": "Vous avez eu moins de sommeil profond que d'habitude. Essayez de vous détendre 30 minutes plus tôt ce soir pour un meilleur repos.", + "blueberry_ring_sleep_alert_text": "Vous avez eu moins de sommeil profond que d'habitude. Essayez de vous détendre 30 minutes plus tôt ce soir pour un meilleur repos.", + "blueberry_ring_heart_rate_alert_title": "Votre rythme cardiaque a été inhabituellement élevé aujourd'hui. Si vous ne vous sentez pas bien, il pourrait être bon de consulter un médecin.", + "blueberry_ring_heart_rate_alert_text": "Votre rythme cardiaque a été inhabituellement élevé aujourd'hui. Si vous ne vous sentez pas bien, il pourrait être bon de consulter un médecin.", + "blueberry_ring_battery_alert_title": "La batterie est faible!", + "blueberry_ring_battery_alert_text": "La batterie de votre Blueberry Ring est faible. Veuillez la charger bientôt pour éviter les lacunes de données.", + "activity_reminder": "Rappel d'activité", + "sleep_insight": "Aperçu du sommeil", + "heart_alert": "Alerte de coeur", + "low_battery": "Batterie faible", + "blueberry_background_notifications_requirements_title": "Ce service nécessite:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth doit être activé", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry doit être accessible", + "auto_sync_started": "Le démarrage automatique de la synchronisation de Blueberry Ring a commencé 🏁", + "no_rings_selected_notification_title": "On dirait que vous n'avez sélectionné aucun Anneaux de Myrtille. ℹ️", + "no_rings_selected_notification_text": "Veuillez vous rendre sur Blueberry Ring DApp pour sélectionner des anneaux.", + "auto_sync_successful_notification_title": "La revendication automatique de Blueberry Ring a réussi ✅", + "auto_sync_successful_notification_text": "Le portefeuille AXS a synchronisé avec succès vos données de ring.", + "already_synced_notification_title": "Oups, déjà synchronisé ℹ️", + "already_synced_notification_text": "Le portefeuille AXS a essayé de synchroniser vos données de ring, mais il semble que vous ayez déjà synchronisé les données de ring aujourd'hui.", + "auto_sync_failed": "L'auto-synchronisation de Blueberry Ring a échoué ❌", + "no_rings_owned_notification": "On dirait que ce portefeuille ne possède pas de Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Synchronisation des données à partir de Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Anneau de Myrtille #{0} : Déjà synchronisé. ℹ️", + "data_synced_successfully_ring": "Bague de Myrtille #{0} : Données synchronisées avec succès. ✅", + "data_syncing_failed": "Bague de Myrtille #{0} : Le processus de synchronisation des données a échoué. ❌", + "blueberry_hooks": "Crochets de Myrtille", + "message": "Message" } \ No newline at end of file diff --git a/assets/flutter_i18n/id.json b/assets/flutter_i18n/id.json index bfcf324c..2d49ae80 100644 --- a/assets/flutter_i18n/id.json +++ b/assets/flutter_i18n/id.json @@ -417,5 +417,41 @@ "save_locally": "Simpan secara lokal", "save_locally_description": "Pastikan untuk menyimpan kunci Anda secara lokal dan kemudian Anda siap untuk melanjutkan.", "axs_storage_permission_use_case": "Dompet AXS membutuhkan akses ke penyimpanan Anda untuk fitur seperti RWA. Data penyimpanan Anda tidak disimpan atau dibagikan dengan pihak ketiga mana pun.", - "local_backup": "Cadangan lokal" + "local_backup": "Cadangan lokal", + "no_description": "Tidak ada deskripsi", + "bluetooth_not_supported": "Bluetooth tidak didukung pada perangkat ini.", + "blueberry_ring_hooks": "Blueberry Ring mengaitkan", + "nearby_blueberry_rings": "Cincin Blueberry terdekat", + "unable_to_continue_bluetooth_is_turned_off": "Tidak dapat melanjutkan, Bluetooth dimatikan!", + "scanning": "Memindai ...", + "blueberry_ring_inactive_alert_title": "Waktunya untuk pergi berjalan-jalan!", + "blueberry_ring_inactive_alert_text": "Anda telah tidak aktif untuk beberapa waktu. Sebuah jalan kaki singkat bisa sangat menyegarkan!", + "blueberry_ring_sleep_alert_title": "Anda telah mendapatkan tidur nyenyak yang lebih sedikit dari biasanya. Coba santai 30 menit lebih awal malam ini untuk istirahat yang lebih baik.", + "blueberry_ring_sleep_alert_text": "Anda telah mendapatkan tidur nyenyak yang lebih sedikit dari biasanya. Coba santai 30 menit lebih awal malam ini untuk istirahat yang lebih baik.", + "blueberry_ring_heart_rate_alert_title": "Denyut jantung Anda hari ini tidak biasanya tinggi. Jika Anda merasa tidak sehat, mungkin baik untuk berkonsultasi dengan dokter.", + "blueberry_ring_heart_rate_alert_text": "Detak jantung Anda hari ini tidak biasanya tinggi. Jika Anda merasa tidak sehat, mungkin baik untuk berkonsultasi dengan dokter.", + "blueberry_ring_battery_alert_title": "Baterai sedang lemah!", + "blueberry_ring_battery_alert_text": "Baterai Cincin Blueberry Anda rendah. Silakan isi ulang segera untuk menghindari kekosongan data.", + "activity_reminder": "Pengingat aktivitas", + "sleep_insight": "Wawasan tidur", + "heart_alert": "Peringatan jantung", + "low_battery": "Baterai rendah", + "blueberry_background_notifications_requirements_title": "Layanan ini memerlukan:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth harus dalam keadaan ON", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry harus dapat dijangkau", + "auto_sync_started": "Sinkronisasi otomatis Blueberry Ring telah dimulai 🏁", + "no_rings_selected_notification_title": "Sepertinya Anda belum memilih Blueberry Rings apa pun. ℹ️", + "no_rings_selected_notification_text": "Silakan menuju ke Blueberry Ring DApp untuk memilih cincin.", + "auto_sync_successful_notification_title": "Berhasil klaim otomatis Blueberry Ring ✅", + "auto_sync_successful_notification_text": "Dompet AXS telah berhasil menyinkronkan data cincin Anda.", + "already_synced_notification_title": "Ups, Sudah disinkronkan ℹ️", + "already_synced_notification_text": "Dompet AXS mencoba untuk menyinkronkan data ring Anda, Tetapi tampaknya Anda telah menyinkronkan data ring hari ini.", + "auto_sync_failed": "Gagal sinkronisasi otomatis Blueberry Ring ❌", + "no_rings_owned_notification": "Sepertinya dompet ini tidak memiliki Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Menyinkronkan data dari Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Cincin Blueberry #{0}: Sudah disinkronkan. ℹ️", + "data_synced_successfully_ring": "Cincin Blueberry #{0}: Data berhasil disinkronkan. ✅", + "data_syncing_failed": "Cincin Blueberry #{0}: Proses sinkronisasi data gagal. ❌", + "blueberry_hooks": "Kait Blueberry", + "message": "Pesan" } \ No newline at end of file diff --git a/assets/flutter_i18n/it.json b/assets/flutter_i18n/it.json index 55d88b5a..0c3cfbe8 100644 --- a/assets/flutter_i18n/it.json +++ b/assets/flutter_i18n/it.json @@ -417,5 +417,41 @@ "save_locally": "Salva localmente", "save_locally_description": "Assicurati di salvare le tue chiavi localmente e poi sei pronto per andare.", "axs_storage_permission_use_case": "Il portafoglio AXS necessita l'accesso al tuo spazio di archiviazione per funzioni come RWA. I tuoi dati di archiviazione non vengono salvati o condivisi con terze parti.", - "local_backup": "Backup locale" + "local_backup": "Backup locale", + "no_description": "Nessuna descrizione", + "bluetooth_not_supported": "Il Bluetooth non è supportato su questo dispositivo.", + "blueberry_ring_hooks": "Ganci dell'Anello di Mirtilli", + "nearby_blueberry_rings": "Anelli di mirtilli nelle vicinanze", + "unable_to_continue_bluetooth_is_turned_off": "Impossibile continuare, il Bluetooth è spento!", + "scanning": "Scansione in corso...", + "blueberry_ring_inactive_alert_title": "È ora di fare una passeggiata!", + "blueberry_ring_inactive_alert_text": "Sei stato inattivo per un po'. Una breve passeggiata potrebbe essere davvero rinvigorente!", + "blueberry_ring_sleep_alert_title": "Hai avuto meno sonno profondo del solito. Prova a rilassarti 30 minuti prima stasera per un riposo migliore.", + "blueberry_ring_sleep_alert_text": "Hai avuto meno sonno profondo del solito. Prova a rilassarti 30 minuti prima stasera per un riposo migliore.", + "blueberry_ring_heart_rate_alert_title": "La tua frequenza cardiaca è stata insolitamente alta oggi. Se ti senti male, potrebbe essere utile consultare un medico.", + "blueberry_ring_heart_rate_alert_text": "La tua frequenza cardiaca è stata insolitamente alta oggi. Se ti senti male, potrebbe essere utile consultare un medico.", + "blueberry_ring_battery_alert_title": "La batteria è scarica!", + "blueberry_ring_battery_alert_text": "La batteria del tuo Blueberry Ring è scarica. Si prega di ricaricare presto per evitare interruzioni dei dati.", + "activity_reminder": "Promemoria di attività", + "sleep_insight": "Intuizione del sonno", + "heart_alert": "Allerta cuore", + "low_battery": "Batteria scarica", + "blueberry_background_notifications_requirements_title": "Questo servizio richiede:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth da attivare", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry deve essere raggiungibile", + "auto_sync_started": "L'avvio della sincronizzazione automatica di Blueberry Ring è iniziato 🏁", + "no_rings_selected_notification_title": "Sembra che non hai selezionato nessun Blueberry Rings. ℹ️", + "no_rings_selected_notification_text": "Si prega di recarsi alla DApp Blueberry Ring per selezionare gli anelli.", + "auto_sync_successful_notification_title": "Il reclamo automatico di Blueberry Ring è stato eseguito con successo ✅", + "auto_sync_successful_notification_text": "Il tuo portafoglio AXS ha sincronizzato con successo i tuoi dati dell'anello.", + "already_synced_notification_title": "Ops, già sincronizzato ℹ️", + "already_synced_notification_text": "Il portafoglio AXS ha cercato di sincronizzare i tuoi dati del ring, ma sembra che tu abbia già sincronizzato i dati del ring oggi.", + "auto_sync_failed": "Blueberry Ring auto-sync non riuscita ❌", + "no_rings_owned_notification": "Sembra che questo portafoglio non possieda nessun Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Sincronizzazione dei dati da Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Anello di Mirtilli #{0}: Già sincronizzato. ℹ️", + "data_synced_successfully_ring": "Anello di Mirtilli #{0}: Dati sincronizzati con successo. ✅", + "data_syncing_failed": "Anello di Mirtilli #{0}: Il processo di sincronizzazione dei dati è fallito. ❌", + "blueberry_hooks": "Ganci Blueberry", + "message": "Messaggio" } \ No newline at end of file diff --git a/assets/flutter_i18n/ja.json b/assets/flutter_i18n/ja.json index f9694cf6..59f634b0 100644 --- a/assets/flutter_i18n/ja.json +++ b/assets/flutter_i18n/ja.json @@ -417,5 +417,41 @@ "save_locally": "ローカルに保存する", "save_locally_description": "あなたのキーをローカルに保存してから、準備が整ったら始めてください。", "axs_storage_permission_use_case": "AXSウォレットは、RWAのような機能のためにあなたのストレージへのアクセスが必要です。あなたのストレージデータは保存されず、また第三者と共有されません。", - "local_backup": "ローカルバックアップ" + "local_backup": "ローカルバックアップ", + "no_description": "説明なし", + "bluetooth_not_supported": "このデバイスではBluetoothはサポートされていません。", + "blueberry_ring_hooks": "ブルーベリーリングフック", + "nearby_blueberry_rings": "近くのブルーベリーリング", + "unable_to_continue_bluetooth_is_turned_off": "Bluetoothがオフになっているため、続行できません!", + "scanning": "スキャン中...", + "blueberry_ring_inactive_alert_title": "散歩に行く時間です!", + "blueberry_ring_inactive_alert_text": "あなたはしばらく活動していませんでした。短い散歩は本当に元気づけることができますよ!", + "blueberry_ring_sleep_alert_title": "あなたは通常より深い眠りを得ていないようです。今夜は30分早くリラックスして、より良い休息を取るように試みてください。", + "blueberry_ring_sleep_alert_text": "あなたは通常より深い眠りを得ていないようです。今夜は30分早くリラックスして、より良い休息を取るように試みてください。", + "blueberry_ring_heart_rate_alert_title": "あなたの心拍数は今日、普段よりも高いです。体調が悪い場合、医者に診てもらうと良いかもしれません。", + "blueberry_ring_heart_rate_alert_text": "あなたの心拍数は今日異常に高いです。体調が悪い場合、医者に診てもらうと良いかもしれません。", + "blueberry_ring_battery_alert_title": "バッテリーが少ないです!", + "blueberry_ring_battery_alert_text": "あなたのブルーベリーリングのバッテリーが低くなっています。データの欠損を避けるために、早めに充電してください。", + "activity_reminder": "活動リマインダー", + "sleep_insight": "睡眠の洞察", + "heart_alert": "ハートアラート", + "low_battery": "バッテリー残量が少ない", + "blueberry_background_notifications_requirements_title": "このサービスには以下が必要です:", + "blueberry_background_notifications_requirements_text_1": "1. ブルートゥースをONにする", + "blueberry_background_notifications_requirements_text_2": "2. ブルーベリーが到達可能になること", + "auto_sync_started": "ブルーベリーリングの自動同期が開始されました 🏁", + "no_rings_selected_notification_title": "あなたはまだブルーベリーリングを選んでいないようです。ℹ️", + "no_rings_selected_notification_text": "リングの選択のために、ブルーベリーリングDAppに移動してください。", + "auto_sync_successful_notification_title": "ブルーベリーリングの自動請求が成功しました✅", + "auto_sync_successful_notification_text": "AXSウォレットはあなたのリングデータを正常に同期しました。", + "already_synced_notification_title": "おっと、すでに同期済みℹ️", + "already_synced_notification_text": "AXSウォレットはあなたのリングデータを同期しようと試みましたが、今日すでにリングデータを同期しているようです。", + "auto_sync_failed": "ブルーベリーリングの自動同期が失敗しました❌", + "no_rings_owned_notification": "このウォレットはブルーベリーリングを一つも所有していないようです。ℹ️", + "syncing_data_from_ring": "ブルーベリーリング #{0} からのデータ同期中。⛏️", + "already_synced_ring": "ブルーベリーリング #{0}: すでに同期済みです。ℹ️", + "data_synced_successfully_ring": "ブルーベリーリング #{0}: データは正常に同期されました。✅", + "data_syncing_failed": "ブルーベリーリング #{0}: データ同期処理が失敗しました。❌", + "blueberry_hooks": "ブルーベリーフック", + "message": "メッセージ" } \ No newline at end of file diff --git a/assets/flutter_i18n/ko.json b/assets/flutter_i18n/ko.json index 08159005..b94e64c0 100644 --- a/assets/flutter_i18n/ko.json +++ b/assets/flutter_i18n/ko.json @@ -417,5 +417,41 @@ "save_locally": "로컬에 저장", "save_locally_description": "당신의 키를 로컬에 저장하십시오, 그런 다음 시작하면 됩니다.", "axs_storage_permission_use_case": "AXS 지갑은 RWA와 같은 기능을 위해 당신의 저장 공간에 접근할 필요가 있습니다. 당신의 저장 데이터는 어떠한 제3자와도 저장되거나 공유되지 않습니다.", - "local_backup": "로컬 백업" + "local_backup": "로컬 백업", + "no_description": "설명 없음", + "bluetooth_not_supported": "이 장치는 블루투스를 지원하지 않습니다.", + "blueberry_ring_hooks": "블루베리 링 훅", + "nearby_blueberry_rings": "근처의 블루베리 반지", + "unable_to_continue_bluetooth_is_turned_off": "Bluetooth가 꺼져 있어 계속할 수 없습니다!", + "scanning": "스캔 중 ...", + "blueberry_ring_inactive_alert_title": "산책하러 가봐야 할 시간이에요!", + "blueberry_ring_inactive_alert_text": "당신은 잠시동안 비활동적이었습니다. 짧은 산책은 정말로 활력을 불어넣을 수 있습니다!", + "blueberry_ring_sleep_alert_title": "보통보다 깊은 수면을 덜 취하고 있습니다. 오늘 밤에는 30분 일찍 푹 쉬기 위해 풀어보세요.", + "blueberry_ring_sleep_alert_text": "보통보다 깊은 수면을 적게 취하고 있습니다. 오늘 밤에는 30분 더 일찍 푹 쉬어 보세요.", + "blueberry_ring_heart_rate_alert_title": "오늘 당신의 심박수가 평소보다 높게 측정되었습니다. 몸 상태가 좋지 않다면, 의사에게 상담하는 것이 좋을 수 있습니다.", + "blueberry_ring_heart_rate_alert_text": "오늘 당신의 심박수가 평소보다 높게 측정되었습니다. 몸 상태가 좋지 않다면, 의사에게 상담하는 것이 좋을 수 있습니다.", + "blueberry_ring_battery_alert_title": "배터리가 부족합니다!", + "blueberry_ring_battery_alert_text": "당신의 블루베리 링의 배터리가 부족합니다. 데이터 손실을 피하기 위해 곧 충전해 주세요.", + "activity_reminder": "활동 알림", + "sleep_insight": "수면 통찰력", + "heart_alert": "하트 알림", + "low_battery": "낮은 배터리", + "blueberry_background_notifications_requirements_title": "이 서비스는 다음을 필요로 합니다:", + "blueberry_background_notifications_requirements_text_1": "블루투스를 켜주세요.", + "blueberry_background_notifications_requirements_text_2": "2. 블루베리가 접근 가능해야 합니다", + "auto_sync_started": "블루베리 링 자동 동기화 시작됨 🏁", + "no_rings_selected_notification_title": "보아하니 당신은 어떠한 블루베리 링도 선택하지 않은 것 같습니다. ℹ️", + "no_rings_selected_notification_text": "다음의 반지를 선택하기 위해 Blueberry Ring DApp으로 이동해 주세요.", + "auto_sync_successful_notification_title": "블루베리 링 자동-클레임 성공 ✅", + "auto_sync_successful_notification_text": "다음의 영어 텍스트를 한국어로 번역하면: AXS 지갑이 성공적으로 당신의 링 데이터를 동기화했습니다.", + "already_synced_notification_title": "이런, 이미 동기화되었습니다 ℹ️", + "already_synced_notification_text": "AXS 지갑이 귀하의 링 데이터를 동기화하려고 시도했지만, 오늘 이미 링 데이터를 동기화한 것 같습니다.", + "auto_sync_failed": "블루베리 링 자동 동기화 실패 ❌", + "no_rings_owned_notification": "이 지갑은 블루베리 링을 소유하고 있지 않은 것 같습니다. ℹ️", + "syncing_data_from_ring": "블루베리 링 #{0}에서 데이터 동기화 중. ⛏️", + "already_synced_ring": "블루베리 링 #{0}: 이미 동기화되었습니다. ℹ️", + "data_synced_successfully_ring": "블루베리 링 #{0}: 데이터 동기화 성공적으로 완료. ✅", + "data_syncing_failed": "블루베리 링 #{0}: 데이터 동기화 과정이 실패했습니다. ❌", + "blueberry_hooks": "블루베리 훅스", + "message": "메시지" } \ No newline at end of file diff --git a/assets/flutter_i18n/nl.json b/assets/flutter_i18n/nl.json index 1b92693e..ee0b0e12 100644 --- a/assets/flutter_i18n/nl.json +++ b/assets/flutter_i18n/nl.json @@ -417,5 +417,41 @@ "save_locally": "Lokaal opslaan", "save_locally_description": "Zorg ervoor dat je je sleutels lokaal opslaat en dan ben je klaar om te gaan.", "axs_storage_permission_use_case": "De AXS Wallet heeft toegang tot uw opslag nodig voor functies zoals RWA. Uw opslaggegevens worden niet opgeslagen of gedeeld met derden.", - "local_backup": "Lokale back-up" + "local_backup": "Lokale back-up", + "no_description": "Geen beschrijving", + "bluetooth_not_supported": "Bluetooth wordt niet ondersteund op dit apparaat.", + "blueberry_ring_hooks": "Blueberry Ring haken", + "nearby_blueberry_rings": "In de buurt Blauwe bessenringen", + "unable_to_continue_bluetooth_is_turned_off": "Kan niet doorgaan, Bluetooth is uitgeschakeld!", + "scanning": "Scannen ...", + "blueberry_ring_inactive_alert_title": "Tijd om te gaan wandelen!", + "blueberry_ring_inactive_alert_text": "Je bent een tijdje inactief geweest. Een korte wandeling kan echt verkwikkend zijn!", + "blueberry_ring_sleep_alert_title": "Je hebt de laatste tijd minder diepe slaap gekregen dan normaal. Probeer vanavond 30 minuten eerder te ontspannen voor een betere rust.", + "blueberry_ring_sleep_alert_text": "Je hebt de laatste tijd minder diepe slaap gekregen dan normaal. Probeer vanavond 30 minuten eerder te ontspannen voor een betere rust.", + "blueberry_ring_heart_rate_alert_title": "Uw hartslag is vandaag ongewoon hoog geweest. Als u zich niet goed voelt, kan het goed zijn om een arts te raadplegen.", + "blueberry_ring_heart_rate_alert_text": "Uw hartslag is vandaag ongewoon hoog geweest. Als u zich niet goed voelt, kan het goed zijn om een arts te raadplegen.", + "blueberry_ring_battery_alert_title": "De batterij is bijna leeg!", + "blueberry_ring_battery_alert_text": "De batterij van je Blueberry Ring is bijna leeg. Laad deze alstublieft snel op om datagaten te voorkomen.", + "activity_reminder": "Activiteit herinnering", + "sleep_insight": "Slaapinzicht", + "heart_alert": "Hart alarm", + "low_battery": "Lage batterij", + "blueberry_background_notifications_requirements_title": "Deze service vereist:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth moet AAN zijn", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry moet bereikbaar zijn", + "auto_sync_started": "Blueberry Ring auto sync gestart 🏁", + "no_rings_selected_notification_title": "Het lijkt erop dat je nog geen Blueberry Rings hebt geselecteerd. ℹ️", + "no_rings_selected_notification_text": "Ga alstublieft naar Blueberry Ring DApp om ringen te selecteren.", + "auto_sync_successful_notification_title": "Blueberry Ring aut-claim succesvol ✅", + "auto_sync_successful_notification_text": "Uw AXS-portemonnee heeft met succes uw ringgegevens gesynchroniseerd.", + "already_synced_notification_title": "Oeps, al gesynchroniseerd ℹ️", + "already_synced_notification_text": "De AXS-portemonnee probeerde je ringgegevens te synchroniseren, maar het lijkt erop dat je de ringgegevens vandaag al hebt gesynchroniseerd.", + "auto_sync_failed": "Blueberry Ring auto-sync mislukt ❌", + "no_rings_owned_notification": "Het lijkt erop dat deze portemonnee geen Blueberry Rings bezit. ℹ️", + "syncing_data_from_ring": "Gegevens synchroniseren van Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Blueberry Ring #{0}: Al gesynchroniseerd. ℹ️", + "data_synced_successfully_ring": "Blueberry Ring #{0}: Gegevens succesvol gesynchroniseerd. ✅", + "data_syncing_failed": "Blueberry Ring #{0}: Gegevens synchronisatieproces mislukt. ❌", + "blueberry_hooks": "Blueberry haken", + "message": "Bericht" } \ No newline at end of file diff --git a/assets/flutter_i18n/pt.json b/assets/flutter_i18n/pt.json index ecf4d054..d7cebf1b 100644 --- a/assets/flutter_i18n/pt.json +++ b/assets/flutter_i18n/pt.json @@ -417,5 +417,41 @@ "save_locally": "Guarde localmente", "save_locally_description": "Certifique-se de salvar suas chaves localmente e então você estará pronto para prosseguir.", "axs_storage_permission_use_case": "A carteira AXS precisa de acesso ao seu armazenamento para recursos como RWA. Seus dados de armazenamento não são salvos ou compartilhados com terceiros.", - "local_backup": "Backup local" + "local_backup": "Backup local", + "no_description": "Sem descrição", + "bluetooth_not_supported": "O Bluetooth não é suportado neste dispositivo.", + "blueberry_ring_hooks": "Blueberry Ring se conecta", + "nearby_blueberry_rings": "Anéis de Mirtilo Próximos", + "unable_to_continue_bluetooth_is_turned_off": "Não é possível continuar, o Bluetooth está desligado!", + "scanning": "Analisando ...", + "blueberry_ring_inactive_alert_title": "Hora de ir para uma caminhada!", + "blueberry_ring_inactive_alert_text": "Você esteve inativo por um tempo. Uma curta caminhada poderia ser realmente revigorante!", + "blueberry_ring_sleep_alert_title": "Você tem tido menos sono profundo do que o habitual. Tente relaxar 30 minutos mais cedo esta noite para um descanso melhor.", + "blueberry_ring_sleep_alert_text": "Você tem tido menos sono profundo do que o habitual. Tente relaxar 30 minutos mais cedo esta noite para um descanso melhor.", + "blueberry_ring_heart_rate_alert_title": "A sua frequência cardíaca tem estado anormalmente alta hoje. Se você se sentir mal, pode ser bom consultar um médico.", + "blueberry_ring_heart_rate_alert_text": "A sua frequência cardíaca tem estado anormalmente alta hoje. Se você se sentir mal, pode ser bom consultar um médico.", + "blueberry_ring_battery_alert_title": "A bateria está fraca!", + "blueberry_ring_battery_alert_text": "A bateria do seu Anel Blueberry está baixa. Por favor, carregue em breve para evitar lacunas de dados.", + "activity_reminder": "Lembrete de atividade", + "sleep_insight": "Percepção do sono", + "heart_alert": "Alerta de coração", + "low_battery": "Bateria baixa", + "blueberry_background_notifications_requirements_title": "Este serviço requer:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth para estar LIGADO", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry para ser alcançável", + "auto_sync_started": "Início automático da sincronização do Blueberry Ring 🏁", + "no_rings_selected_notification_title": "Parece que você não selecionou nenhum Anel de Mirtilo. ℹ️", + "no_rings_selected_notification_text": "Por favor, vá para o DApp Blueberry Ring para selecionar anéis.", + "auto_sync_successful_notification_title": "Sucesso na auto-reivindicação do Blueberry Ring ✅", + "auto_sync_successful_notification_text": "A carteira AXS foi sincronizada com sucesso com os seus dados de anel.", + "already_synced_notification_title": "Ops, já sincronizado ℹ️", + "already_synced_notification_text": "A carteira AXS tentou sincronizar seus dados de anel, mas parece que você já sincronizou os dados do anel hoje.", + "auto_sync_failed": "Falha na sincronização automática do Blueberry Ring ❌", + "no_rings_owned_notification": "Parece que esta carteira não possui nenhum Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Sincronizando dados do Anel de Mirtilo #{0}. ⛏️", + "already_synced_ring": "Anel de Mirtilo #{0}: Já sincronizado. ℹ️", + "data_synced_successfully_ring": "Anel de Mirtilo #{0}: Dados sincronizados com sucesso. ✅", + "data_syncing_failed": "Anel de Mirtilo #{0}: Processo de sincronização de dados falhou. ❌", + "blueberry_hooks": "Ganchos de Mirtilo", + "message": "Mensagem" } \ No newline at end of file diff --git a/assets/flutter_i18n/ro.json b/assets/flutter_i18n/ro.json index 677df4c4..4bde8ddb 100644 --- a/assets/flutter_i18n/ro.json +++ b/assets/flutter_i18n/ro.json @@ -417,5 +417,41 @@ "save_locally": "Salvează local", "save_locally_description": "Asigurați-vă că salvați cheile local și apoi sunteți gata de plecare.", "axs_storage_permission_use_case": "Portofelul AXS are nevoie de acces la spațiul tău de stocare pentru funcții precum RWA. Datele tale de stocare nu sunt salvate sau partajate cu terțe părți.", - "local_backup": "Copie de rezervă locală" + "local_backup": "Copie de rezervă locală", + "no_description": "Fără descriere", + "bluetooth_not_supported": "Bluetooth nu este suportat pe acest dispozitiv.", + "blueberry_ring_hooks": "Cârligele Blueberry Ring", + "nearby_blueberry_rings": "Inele de afine din apropiere", + "unable_to_continue_bluetooth_is_turned_off": "Imposibil de continuat, Bluetooth este oprit!", + "scanning": "Scanare...", + "blueberry_ring_inactive_alert_title": "Timpul să mergem la plimbare!", + "blueberry_ring_inactive_alert_text": "Ai fost inactiv pentru o perioadă. O scurtă plimbare ar putea fi cu adevărat revigorantă!", + "blueberry_ring_sleep_alert_title": "Ai avut un somn mai puțin profund decât de obicei. Încearcă să te relaxezi cu 30 de minute mai devreme în seara asta pentru un odihnă mai bună.", + "blueberry_ring_sleep_alert_text": "Ai avut un somn mai puțin profund decât de obicei. Încearcă să te relaxezi cu 30 de minute mai devreme în seara asta pentru un odihnă mai bună.", + "blueberry_ring_heart_rate_alert_title": "Ritmul tău cardiac a fost neobișnuit de mare astăzi. Dacă te simți rău, ar fi bine să consulți un medic.", + "blueberry_ring_heart_rate_alert_text": "Ritmul cardiac a fost neobișnuit de ridicat astăzi. Dacă te simți rău, ar fi bine să consulți un medic.", + "blueberry_ring_battery_alert_title": "Bateria este descărcată!", + "blueberry_ring_battery_alert_text": "Bateria inelului tău Blueberry este descărcată. Te rugăm să o încarci în curând pentru a evita lacunele de date.", + "activity_reminder": "Reamintire de activitate", + "sleep_insight": "Intuiție despre somn", + "heart_alert": "Alertă de inimă", + "low_battery": "Baterie scăzută", + "blueberry_background_notifications_requirements_title": "Acest serviciu necesită:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth să fie PORNIT", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry să fie accesibil", + "auto_sync_started": "Sincronizarea automată a Blueberry Ring a început 🏁", + "no_rings_selected_notification_title": "Se pare că nu ai selectat niciun Inel de Afine. ℹ️", + "no_rings_selected_notification_text": "Vă rugăm să mergeți la Blueberry Ring DApp pentru a selecta inelele.", + "auto_sync_successful_notification_title": "Succes la auto-revendicarea Blueberry Ring ✅", + "auto_sync_successful_notification_text": "Portofelul AXS a sincronizat cu succes datele inelului tău.", + "already_synced_notification_title": "Ups, deja sincronizat ℹ️", + "already_synced_notification_text": "Portofelul AXS a încercat să sincronizeze datele tale de inel, dar se pare că ai sincronizat deja datele de inel astăzi.", + "auto_sync_failed": "Eșec la sincronizarea automată a Blueberry Ring ❌", + "no_rings_owned_notification": "Se pare că acest portofel nu deține niciun Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Sincronizare date de la Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Inelul Blueberry #{0}: Deja sincronizat. ℹ️", + "data_synced_successfully_ring": "Inelul Blueberry #{0}: Datele au fost sincronizate cu succes. ✅", + "data_syncing_failed": "Inelul Blueberry #{0}: Procesul de sincronizare a datelor a eșuat. ❌", + "blueberry_hooks": "Cârlige de afine", + "message": "Mesaj" } \ No newline at end of file diff --git a/assets/flutter_i18n/ru.json b/assets/flutter_i18n/ru.json index 63997a0c..60060a13 100644 --- a/assets/flutter_i18n/ru.json +++ b/assets/flutter_i18n/ru.json @@ -417,5 +417,41 @@ "save_locally": "Сохранить локально", "save_locally_description": "Убедитесь, что вы сохранили свои ключи локально, и тогда вы готовы к работе.", "axs_storage_permission_use_case": "Кошелек AXS требует доступа к вашему хранилищу для функций, таких как RWA. Ваши данные хранения не сохраняются и не передаются третьим сторонам.", - "local_backup": "Локальное резервное копирование" + "local_backup": "Локальное резервное копирование", + "no_description": "Нет описания", + "bluetooth_not_supported": "Bluetooth не поддерживается на этом устройстве.", + "blueberry_ring_hooks": "Крючки Blueberry Ring", + "nearby_blueberry_rings": "Ближайшие кольца Блуберри", + "unable_to_continue_bluetooth_is_turned_off": "Невозможно продолжить, Bluetooth выключен!", + "scanning": "Сканирование...", + "blueberry_ring_inactive_alert_title": "Пора идти на прогулку!", + "blueberry_ring_inactive_alert_text": "Вы были неактивны некоторое время. Короткая прогулка могла бы быть действительно бодрящей!", + "blueberry_ring_sleep_alert_title": "Вы спите меньше глубокого сна, чем обычно. Попробуйте расслабиться на 30 минут раньше сегодня вечером для лучшего отдыха.", + "blueberry_ring_sleep_alert_text": "Вы спите меньше глубокого сна, чем обычно. Попробуйте расслабиться на 30 минут раньше сегодня вечером для лучшего отдыха.", + "blueberry_ring_heart_rate_alert_title": "Ваш пульс сегодня необычайно высок. Если вы чувствуете себя нездорово, может быть хорошей идеей обратиться к врачу.", + "blueberry_ring_heart_rate_alert_text": "Ваш пульс сегодня необычайно высокий. Если вы чувствуете себя плохо, было бы неплохо обратиться к врачу.", + "blueberry_ring_battery_alert_title": "Заряд батареи низкий!", + "blueberry_ring_battery_alert_text": "Заряд батареи вашего Blueberry Ring низкий. Пожалуйста, зарядите его в ближайшее время, чтобы избежать пропусков в данных.", + "activity_reminder": "Напоминание о активности", + "sleep_insight": "Инсайт во время сна", + "heart_alert": "Оповещение сердца", + "low_battery": "Низкий уровень заряда", + "blueberry_background_notifications_requirements_title": "Этот сервис требует:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth должен быть включен", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry должен быть доступен", + "auto_sync_started": "Автосинхронизация Blueberry Ring началась 🏁", + "no_rings_selected_notification_title": "Похоже, вы не выбрали ни одного Blueberry Rings. ℹ️", + "no_rings_selected_notification_text": "Пожалуйста, перейдите в Blueberry Ring DApp для выбора колец.", + "auto_sync_successful_notification_title": "Успешное авто-выполнение Blueberry Ring ✅", + "auto_sync_successful_notification_text": "Кошелек AXS успешно синхронизировал ваши данные кольца.", + "already_synced_notification_title": "Упс, уже синхронизировано ℹ️", + "already_synced_notification_text": "Кошелек AXS попытался синхронизировать ваши данные кольца, но похоже, что вы уже синхронизировали данные кольца сегодня.", + "auto_sync_failed": "Синхронизация Blueberry Ring не удалась ❌", + "no_rings_owned_notification": "Похоже, что в этом кошельке нет Blueberry Rings. ℹ️", + "syncing_data_from_ring": "Синхронизация данных с Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Черничное кольцо #{0}: Уже синхронизировано. ℹ️", + "data_synced_successfully_ring": "Кольцо Blueberry #{0}: Данные успешно синхронизированы. ✅", + "data_syncing_failed": "Черничное кольцо #{0}: Процесс синхронизации данных не удался. ❌", + "blueberry_hooks": "Крючки для черники", + "message": "Сообщение" } \ No newline at end of file diff --git a/assets/flutter_i18n/tr.json b/assets/flutter_i18n/tr.json index bc965e61..2ac40c4b 100644 --- a/assets/flutter_i18n/tr.json +++ b/assets/flutter_i18n/tr.json @@ -417,5 +417,41 @@ "save_locally": "Yerel olarak kaydet", "save_locally_description": "Anahtarlarınızı yerel olarak kaydettiğinizden emin olun ve sonra işlem yapmaya hazırsınız.", "axs_storage_permission_use_case": "AXS Cüzdanı, RWA gibi özellikler için depolama alanınıza erişim gerektirir. Depolama verileriniz hiçbir üçüncü taraf ile kaydedilmez veya paylaşılmaz.", - "local_backup": "Yerel yedekleme" + "local_backup": "Yerel yedekleme", + "no_description": "Açıklama yok", + "bluetooth_not_supported": "Bu cihazda Bluetooth desteklenmiyor.", + "blueberry_ring_hooks": "Mavi Yüzük kanca", + "nearby_blueberry_rings": "Yakındaki Yaban Mersini halkaları", + "unable_to_continue_bluetooth_is_turned_off": "Devam edilemiyor, Bluetooth kapalı!", + "scanning": "Tarama ...", + "blueberry_ring_inactive_alert_title": "Yürüyüşe çıkma zamanı!", + "blueberry_ring_inactive_alert_text": "Bir süre boyunca hareketsiz kaldınız. Kısa bir yürüyüş gerçekten canlandırıcı olabilir!", + "blueberry_ring_sleep_alert_title": "Daha önceki dönemlere kıyasla daha az derin uyku uyuyorsunuz. Daha iyi dinlenmek için bu gece 30 dakika daha erken rahatlamayı deneyin.", + "blueberry_ring_sleep_alert_text": "Daha önceki dönemlere kıyasla daha az derin uyku uyuyorsunuz. Daha iyi dinlenmek için bu gece 30 dakika daha erken rahatlamayı deneyin.", + "blueberry_ring_heart_rate_alert_title": "Bugün kalp atış hızınız olağanın üzerinde yüksek olmuş. Kendinizi iyi hissetmiyorsanız, bir doktora başvurmanız iyi olabilir.", + "blueberry_ring_heart_rate_alert_text": "Bugün kalp atış hızınız olağanın üzerinde yüksek olmuş. Kendinizi iyi hissetmiyorsanız, bir doktora başvurmanız iyi olabilir.", + "blueberry_ring_battery_alert_title": "Pil düşük!", + "blueberry_ring_battery_alert_text": "Mavi Yüzük'ünüzün pil seviyesi düşük. Veri boşluklarını önlemek için lütfen yakında şarj edin.", + "activity_reminder": "Aktivite hatırlatıcısı", + "sleep_insight": "Uyku içgörüsü", + "heart_alert": "Kalp alarmı", + "low_battery": "Düşük pil", + "blueberry_background_notifications_requirements_title": "Bu hizmet şunları gerektirir:", + "blueberry_background_notifications_requirements_text_1": "Bluetooth'un AÇIK olması", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry'nin ulaşılabilir olması", + "auto_sync_started": "Yabanmersini Halkası otomatik senkronizasyon başladı 🏁", + "no_rings_selected_notification_title": "Görünüşe göre herhangi bir Blueberry Rings seçmemişsiniz. ℹ️", + "no_rings_selected_notification_text": "Lütfen yüzük seçmek için Blueberry Ring DApp'e gidin.", + "auto_sync_successful_notification_title": "Blueberry Ring otomatik talep başarılı ✅", + "auto_sync_successful_notification_text": "AXS cüzdanınız başarıyla halka verilerinizi senkronize etti.", + "already_synced_notification_title": "Hata, Zaten senkronize edildi ℹ️", + "already_synced_notification_text": "AXS cüzdanınız yüzük verilerinizi senkronize etmeye çalıştı, ancak görünüşe göre yüzük verilerinizi bugün senkronize etmişsiniz.", + "auto_sync_failed": "Blueberry Ring otomatik senkronizasyon başarısız oldu ❌", + "no_rings_owned_notification": "Görünüşe göre bu cüzdanın hiç Mavi Yüzük'ü yok. ℹ️", + "syncing_data_from_ring": "Blueberry Ring #{0} 'dan veri senkronizasyonu yapılıyor. ⛏️", + "already_synced_ring": "Yaban Mersini Halkası #{0}: Zaten senkronize edildi. ℹ️", + "data_synced_successfully_ring": "Yaban Mersini Halkası #{0}: Veri başarıyla senkronize edildi. ✅", + "data_syncing_failed": "Yaban Mersini Halkası #{0}: Veri senkronizasyon işlemi başarısız oldu. ❌", + "blueberry_hooks": "Yaban Mersini Çengelleri", + "message": "Mesaj" } \ No newline at end of file diff --git a/assets/flutter_i18n/vi.json b/assets/flutter_i18n/vi.json index 7a03cf27..08224dc2 100644 --- a/assets/flutter_i18n/vi.json +++ b/assets/flutter_i18n/vi.json @@ -417,5 +417,41 @@ "save_locally": "Lưu trữ cục bộ", "save_locally_description": "Hãy chắc chắn lưu lại khóa của bạn ở cục bộ và sau đó bạn đã sẵn sàng để tiếp tục.", "axs_storage_permission_use_case": "Ví AXS cần quyền truy cập vào bộ nhớ của bạn để sử dụng các tính năng như RWA. Dữ liệu lưu trữ của bạn không được lưu lại hoặc chia sẻ với bất kỳ bên thứ ba nào.", - "local_backup": "Sao lưu cục bộ" + "local_backup": "Sao lưu cục bộ", + "no_description": "Không mô tả", + "bluetooth_not_supported": "Bluetooth không được hỗ trợ trên thiết bị này.", + "blueberry_ring_hooks": "Móc Blueberry Ring", + "nearby_blueberry_rings": "Vòng Blueberry gần đây", + "unable_to_continue_bluetooth_is_turned_off": "Không thể tiếp tục vì Bluetooth đã bị tắt!", + "scanning": "Đang quét...", + "blueberry_ring_inactive_alert_title": "Đã đến lúc đi dạo!", + "blueberry_ring_inactive_alert_text": "Bạn đã không hoạt động trong một thời gian. Một cuộc dạo chơi ngắn có thể thực sự làm tăng sức sống!", + "blueberry_ring_sleep_alert_title": "Bạn đã có ít giấc ngủ sâu hơn so với bình thường. Hãy thử thư giãn 30 phút sớm hơn tối nay để có giấc ngủ tốt hơn.", + "blueberry_ring_sleep_alert_text": "Bạn đã ngủ không sâu như thường lệ. Hãy thử thư giãn 30 phút sớm hơn tối nay để có giấc ngủ tốt hơn.", + "blueberry_ring_heart_rate_alert_title": "Tốc độ nhịp tim của bạn hôm nay bất thường cao. Nếu bạn cảm thấy không khỏe, có thể nên đi kiểm tra với bác sĩ.", + "blueberry_ring_heart_rate_alert_text": "Tốc độ nhịp tim của bạn hôm nay bất thường cao. Nếu bạn cảm thấy không khỏe, có thể nên đi kiểm tra với bác sĩ.", + "blueberry_ring_battery_alert_title": "Pin đang yếu!", + "blueberry_ring_battery_alert_text": "Pin của Chiếc Nhẫn Blueberry của bạn đang yếu. Vui lòng sạc sớm để tránh mất dữ liệu.", + "activity_reminder": "Nhắc nhở hoạt động", + "sleep_insight": "Sự hiểu biết về giấc ngủ", + "heart_alert": "Cảnh báo tim", + "low_battery": "Pin yếu", + "blueberry_background_notifications_requirements_title": "Dịch vụ này yêu cầu:", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth cần được BẬT", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry cần có thể tiếp cận được", + "auto_sync_started": "Bắt đầu tự động đồng bộ Blueberry Ring 🏁", + "no_rings_selected_notification_title": "Có vẻ như bạn chưa chọn bất kỳ Nhẫn Blueberry nào. ℹ️", + "no_rings_selected_notification_text": "Vui lòng đến ứng dụng phi tập trung Blueberry Ring để chọn nhẫn.", + "auto_sync_successful_notification_title": "Thành công trong việc tự động yêu cầu Blueberry Ring ✅", + "auto_sync_successful_notification_text": "Ví AXS đã đồng bộ thành công dữ liệu vòng của bạn", + "already_synced_notification_title": "Ồ, đã được đồng bộ hóa ℹ️", + "already_synced_notification_text": "Ví AXS đã cố gắng đồng bộ dữ liệu vòng của bạn, Nhưng có vẻ như bạn đã đồng bộ dữ liệu vòng hôm nay.", + "auto_sync_failed": "Vòng Blueberry tự đồng bộ thất bại ❌", + "no_rings_owned_notification": "Dường như ví này không sở hữu bất kỳ Blueberry Rings nào. ℹ️", + "syncing_data_from_ring": "Đồng bộ hóa dữ liệu từ Blueberry Ring #{0}. ⛏️", + "already_synced_ring": "Vòng Blueberry #{0}: Đã được đồng bộ. ℹ️", + "data_synced_successfully_ring": "Vòng Blueberry #{0}: Dữ liệu đã được đồng bộ thành công. ✅", + "data_syncing_failed": "Vòng Blueberry #{0}: Quá trình đồng bộ hóa dữ liệu thất bại. ❌", + "blueberry_hooks": "Móc Blueberry", + "message": "Tin nhắn" } \ No newline at end of file diff --git a/assets/flutter_i18n/zh_CN.json b/assets/flutter_i18n/zh_CN.json index 9c00f609..76df5729 100644 --- a/assets/flutter_i18n/zh_CN.json +++ b/assets/flutter_i18n/zh_CN.json @@ -417,5 +417,41 @@ "save_locally": "在本地保存", "save_locally_description": "确保将您的密钥本地保存,然后就可以开始了。", "axs_storage_permission_use_case": "AXS钱包需要访问您的存储空间以使用如RWA等功能。您的存储数据不会被保存或与任何第三方共享。", - "local_backup": "本地备份" + "local_backup": "本地备份", + "no_description": "无描述", + "bluetooth_not_supported": "这个设备不支持蓝牙。", + "blueberry_ring_hooks": "蓝莓环钩", + "nearby_blueberry_rings": "附近的蓝莓环", + "unable_to_continue_bluetooth_is_turned_off": "无法继续,蓝牙已关闭!", + "scanning": "正在扫描...", + "blueberry_ring_inactive_alert_title": "是时候去散步了!", + "blueberry_ring_inactive_alert_text": "您已经有一段时间没有活动了。短暂的散步可能会让你精神焕发!", + "blueberry_ring_sleep_alert_title": "你最近的深度睡眠时间比平时少。尝试在今晚提前30分钟放松,以获得更好的休息。", + "blueberry_ring_sleep_alert_text": "你最近的深度睡眠时间比平时少。尝试在今晚提前30分钟放松,以获得更好的休息。", + "blueberry_ring_heart_rate_alert_title": "你今天的心率异常升高。如果你感觉不适,可能需要去看医生。", + "blueberry_ring_heart_rate_alert_text": "你今天的心率异常升高。如果你感到不适,最好去看医生。", + "blueberry_ring_battery_alert_title": "电池电量低!", + "blueberry_ring_battery_alert_text": "您的Blueberry Ring电池电量低。请尽快充电以避免数据断裂。", + "activity_reminder": "活动提醒", + "sleep_insight": "睡眠洞察", + "heart_alert": "心脏警报", + "low_battery": "电池电量低", + "blueberry_background_notifications_requirements_title": "此服务需要:", + "blueberry_background_notifications_requirements_text_1": "1. 需要打开蓝牙", + "blueberry_background_notifications_requirements_text_2": "2. 蓝莓需要能够被联系到", + "auto_sync_started": "蓝莓环自动同步开始🏁", + "no_rings_selected_notification_title": "看起来你还没有选择任何蓝莓环。ℹ️", + "no_rings_selected_notification_text": "请前往Blueberry Ring DApp选择戒指。", + "auto_sync_successful_notification_title": "蓝莓环自动领取成功 ✅", + "auto_sync_successful_notification_text": "AXS钱包已成功同步您的环数据。", + "already_synced_notification_title": "哎呀,已经同步ℹ️", + "already_synced_notification_text": "AXS钱包试图同步您的环数据,但看起来您今天已经同步了环数据。", + "auto_sync_failed": "蓝莓环自动同步失败 ❌", + "no_rings_owned_notification": "看起来这个钱包并未拥有任何蓝莓环币。ℹ️", + "syncing_data_from_ring": "从Blueberry Ring #{0}同步数据。⛏️", + "already_synced_ring": "蓝莓环 # {0}:已经同步。ℹ️", + "data_synced_successfully_ring": "蓝莓环 # {0}:数据同步成功。✅", + "data_syncing_failed": "蓝莓环#{0}:数据同步过程失败。❌", + "blueberry_hooks": "蓝莓钩子", + "message": "消息" } \ No newline at end of file diff --git a/assets/flutter_i18n/zh_TW.json b/assets/flutter_i18n/zh_TW.json index b78e8c40..295eb9bd 100644 --- a/assets/flutter_i18n/zh_TW.json +++ b/assets/flutter_i18n/zh_TW.json @@ -417,5 +417,41 @@ "save_locally": "在本地保存", "save_locally_description": "確保將您的密鑰本地保存,然後就可以開始了。", "axs_storage_permission_use_case": "AXS錢包需要訪問您的存储空間以使用如RWA等功能。您的存儲數據不會被保存或與任何第三方共享。", - "local_backup": "本地備份" + "local_backup": "本地備份", + "no_description": "無描述", + "bluetooth_not_supported": "此設備不支援藍牙。", + "blueberry_ring_hooks": "藍莓環鉤", + "nearby_blueberry_rings": "附近的藍莓環", + "unable_to_continue_bluetooth_is_turned_off": "無法繼續,藍牙已關閉!", + "scanning": "正在掃描...", + "blueberry_ring_inactive_alert_title": "該去散步了!", + "blueberry_ring_inactive_alert_text": "您已經有一段時間沒有活動了。短暫的散步可能真的很振奮人心!", + "blueberry_ring_sleep_alert_title": "您最近的深度睡眠時間比平常少。試著今晚提早30分鐘放鬆心情,以獲得更好的休息。", + "blueberry_ring_sleep_alert_text": "您最近的深度睡眠時間比平常少。試著今晚提早30分鐘放鬆心情,以獲得更好的休息。", + "blueberry_ring_heart_rate_alert_title": "你今天的心率異常地高。如果你感到不適,可能需要去看醫生。", + "blueberry_ring_heart_rate_alert_text": "你今天的心率異常地高。如果你感到不適,可能需要去看醫生。", + "blueberry_ring_battery_alert_title": "電池電量低!", + "blueberry_ring_battery_alert_text": "您的Blueberry Ring電池電量低。請儘快充電以避免數據出現間隙。", + "activity_reminder": "活動提醒", + "sleep_insight": "睡眠洞察", + "heart_alert": "心臟警報", + "low_battery": "低電量", + "blueberry_background_notifications_requirements_title": "此服務需要:", + "blueberry_background_notifications_requirements_text_1": "1. 開啟藍牙", + "blueberry_background_notifications_requirements_text_2": "2. 藍莓需能被聯繫到", + "auto_sync_started": "藍莓環自動同步已開始 🏁", + "no_rings_selected_notification_title": "看起來您還沒有選擇任何藍莓環。ℹ️", + "no_rings_selected_notification_text": "請前往Blueberry Ring DApp選擇戒指。", + "auto_sync_successful_notification_title": "藍莓環自動索取成功 ✅", + "auto_sync_successful_notification_text": "AXS 錢包已成功同步您的環數據", + "already_synced_notification_title": "哎呀,已經同步了ℹ️", + "already_synced_notification_text": "AXS錢包嘗試同步您的環形數據,但看起來您今天已經同步了環形數據。", + "auto_sync_failed": "藍莓環自動同步失敗❌", + "no_rings_owned_notification": "看起來這個錢包並未擁有任何藍莓環。ℹ️", + "syncing_data_from_ring": "從Blueberry Ring #{0}同步數據。⛏️", + "already_synced_ring": "藍莓環#{0}:已經同步。ℹ️", + "data_synced_successfully_ring": "藍莓環#{0}:數據同步成功。✅", + "data_syncing_failed": "藍莓環#{0}:數據同步過程失敗。❌", + "blueberry_hooks": "藍莓鉤子", + "message": "訊息" } \ No newline at end of file From 2979cd4df4764e9b8a1c57cd5c162c9ca772c783 Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 16 Aug 2024 11:54:47 +0330 Subject: [PATCH 44/45] fix: Update version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index cdbfb94a..0931ab71 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.4.8 +version: 2.4.9 environment: sdk: ">=2.19.0 <3.0.0" From c7dad4a9e92141bde4a0efb87704b842ba13248d Mon Sep 17 00:00:00 2001 From: reasje Date: Fri, 16 Aug 2024 11:55:58 +0330 Subject: [PATCH 45/45] fix: Support http for dapps --- .../presentation/responsive_layout/dapps_layout/build_card.dart | 2 ++ .../add_dapp/presentation/add_bookmark_presenter.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/features/dapps/presentation/responsive_layout/dapps_layout/build_card.dart b/lib/features/dapps/presentation/responsive_layout/dapps_layout/build_card.dart index 574fa2ba..fa2d6168 100644 --- a/lib/features/dapps/presentation/responsive_layout/dapps_layout/build_card.dart +++ b/lib/features/dapps/presentation/responsive_layout/dapps_layout/build_card.dart @@ -76,6 +76,8 @@ Widget buildCard( ) : image.contains( 'https', + ) || image.contains( + 'http', ) ? image.contains( 'svg', diff --git a/lib/features/dapps/subfeatures/add_dapp/presentation/add_bookmark_presenter.dart b/lib/features/dapps/subfeatures/add_dapp/presentation/add_bookmark_presenter.dart index 5d68ec3e..cacfeadf 100644 --- a/lib/features/dapps/subfeatures/add_dapp/presentation/add_bookmark_presenter.dart +++ b/lib/features/dapps/subfeatures/add_dapp/presentation/add_bookmark_presenter.dart @@ -18,7 +18,7 @@ class AddBookmarkPresenter extends CompletePresenter { Future onSave() async { String url = urlController.text; - url = url.contains('https') ? url : 'https://$url'; + url = url.contains('https') || url.contains('http') ? url : 'https://$url'; loading = true; try {