From ed9d97587359815f512fecb9fe126933ce8f0b04 Mon Sep 17 00:00:00 2001 From: Thiago Carvalho <32248947+thiagocarvalhodev@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:58:10 -0300 Subject: [PATCH 1/2] feat(autoupdate) - default to last assigned name --- lib/arns/domain/arns_repository.dart | 22 ++++++++++++ .../blocs/upload_manifest_options_bloc.dart | 34 +++++++++++++++++++ .../manifest_options/manifest_options.dart | 4 +++ .../utils/get_literal_arns_record_name.dart | 10 ++++++ 4 files changed, 70 insertions(+) diff --git a/lib/arns/domain/arns_repository.dart b/lib/arns/domain/arns_repository.dart index 16a025fac..ef6f53b0d 100644 --- a/lib/arns/domain/arns_repository.dart +++ b/lib/arns/domain/arns_repository.dart @@ -33,6 +33,8 @@ abstract class ARNSRepository { Future saveAllFilesWithAssignedNames(); Future> getActiveARNSRecordsForFile(String fileId); Future waitForARNSRecordsToUpdate(); + Future getUndernameByDomainAndName( + String domain, String name); factory ARNSRepository({ required ArioSDK sdk, @@ -371,6 +373,26 @@ class _ARNSRepository implements ARNSRepository { await _getARNSUndernamesCompleter!.future; } + + @override + Future getUndernameByDomainAndName( + String domain, String name) async { + if (_cachedUndernames.isEmpty) { + await waitForARNSRecordsToUpdate(); + } + + if (_cachedUndernames[domain] == null) { + throw Exception('Domain not cached'); + } + + final undername = _cachedUndernames[domain]![name]; + + if (undername == null) { + throw Exception('Undername not cached'); + } + + return undername; + } } AntRecord toAntRecordFromSDK(sdk.ANTRecord record) { diff --git a/lib/core/upload/view/blocs/upload_manifest_options_bloc.dart b/lib/core/upload/view/blocs/upload_manifest_options_bloc.dart index 784a3eca9..83339594b 100644 --- a/lib/core/upload/view/blocs/upload_manifest_options_bloc.dart +++ b/lib/core/upload/view/blocs/upload_manifest_options_bloc.dart @@ -1,7 +1,10 @@ import 'package:ardrive/arns/domain/arns_repository.dart'; +import 'package:ardrive/arns/utils/parse_assigned_names_from_string.dart'; import 'package:ardrive/authentication/ardrive_auth.dart'; import 'package:ardrive/models/models.dart'; +import 'package:ardrive/utils/logger.dart'; import 'package:ario_sdk/ario_sdk.dart'; +import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -57,6 +60,37 @@ class UploadManifestOptionsBloc on((event, emit) async { final walletAddress = await arDriveAuth.getWalletAddress(); _ants = await arnsRepository.getAntRecordsForWallet(walletAddress!); + + for (var file in manifestFiles) { + if (file.manifest.assignedNames != null && + file.manifest.assignedNames!.isNotEmpty) { + final assignedNames = + parseAssignedNamesFromString(file.manifest.assignedNames!); + final assignedName = assignedNames!.first; + + final (domain, undername) = splitArNSRecordName(assignedName); + + /// For now, we only support adding one name + final antRecord = _ants!.firstWhereOrNull((e) => e.domain == domain); + + if (antRecord != null) { + try { + final existingUndername = await arnsRepository + .getUndernameByDomainAndName(domain, undername ?? '@'); + + add(SelectManifest(manifest: file.manifest)); + add(LinkManifestToUndername( + manifest: file.manifest, + antRecord: antRecord, + undername: existingUndername, + )); + } catch (e) { + logger.e('Error getting undername: $e'); + } + } + } + } + emit(_createReadyState()); }); diff --git a/lib/core/upload/view/manifest_options/manifest_options.dart b/lib/core/upload/view/manifest_options/manifest_options.dart index 755957b05..24880cc2d 100644 --- a/lib/core/upload/view/manifest_options/manifest_options.dart +++ b/lib/core/upload/view/manifest_options/manifest_options.dart @@ -1,5 +1,6 @@ import 'package:ardrive/components/components.dart'; import 'package:ardrive/core/upload/view/blocs/upload_manifest_options_bloc.dart'; +import 'package:ardrive/utils/logger.dart'; import 'package:ardrive_ui/ardrive_ui.dart'; import 'package:ario_sdk/ario_sdk.dart'; import 'package:flutter/material.dart'; @@ -31,6 +32,8 @@ class ManifestOptions extends StatelessWidget { final file = manifestFiles.elementAt(index).manifest; final isSelected = selectedManifestIds.contains(file.id); + logger.d('Is selected: $isSelected'); + return _ManifestOptionTile( manifestSelection: manifestFiles.elementAt(index), isSelected: isSelected, @@ -143,6 +146,7 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> { Flexible( flex: 1, child: ArDriveCheckBox( + key: ValueKey(widget.isSelected), checked: widget.isSelected, onChange: (value) { if (value) { diff --git a/packages/ario_sdk/lib/src/utils/get_literal_arns_record_name.dart b/packages/ario_sdk/lib/src/utils/get_literal_arns_record_name.dart index bcd4c8dd6..bba245d23 100644 --- a/packages/ario_sdk/lib/src/utils/get_literal_arns_record_name.dart +++ b/packages/ario_sdk/lib/src/utils/get_literal_arns_record_name.dart @@ -7,3 +7,13 @@ String getLiteralARNSRecordName(ARNSUndername undername) { return '${undername.name}_${undername.domain}'; } +/// Splits an ARNS record name into its literal name and domain. +/// If the name is not in the format [name]_[domain], it returns [name] and null. +(String, String?) splitArNSRecordName(String name) { + if (name.contains('_')) { + return (name.split('_').first, name.split('_').last); + } + + return (name, null); +} +// From 8bab47d74f0b94fc9c27b58d1cd5bdf08d5da975 Mon Sep 17 00:00:00 2001 From: Thiago Carvalho <32248947+thiagocarvalhodev@users.noreply.github.com> Date: Sun, 17 Nov 2024 14:34:03 -0300 Subject: [PATCH 2/2] create new undername --- lib/arns/domain/arns_repository.dart | 7 + .../assign_name_bloc/assign_name_bloc.dart | 60 +++++--- .../assign_name_bloc/assign_name_event.dart | 17 ++- .../assign_name_bloc/assign_name_state.dart | 30 ++-- lib/arns/presentation/assign_name_modal.dart | 49 ++++++- lib/arns/presentation/create_undername.dart | 129 ++++++++++++++++++ .../create_undername_bloc.dart | 51 +++++++ .../create_undername_event.dart | 18 +++ .../create_undername_state.dart | 26 ++++ lib/components/create_manifest_form.dart | 9 +- lib/components/upload_form.dart | 17 ++- packages/ario_sdk/lib/src/ario_sdk.dart | 4 +- .../lib/src/implementations/ario_sdk_web.dart | 28 +++- .../implementations/ario_sdk_web_stub.dart | 7 + .../lib/src/models/arns_name_model.dart | 24 ++++ packages/ario_sdk/lib/src/models/models.dart | 2 + .../lib/src/models/response_object.dart | 12 +- 17 files changed, 428 insertions(+), 62 deletions(-) create mode 100644 lib/arns/presentation/create_undername.dart create mode 100644 lib/arns/presentation/create_undername/create_undername_bloc.dart create mode 100644 lib/arns/presentation/create_undername/create_undername_event.dart create mode 100644 lib/arns/presentation/create_undername/create_undername_state.dart create mode 100644 packages/ario_sdk/lib/src/models/arns_name_model.dart diff --git a/lib/arns/domain/arns_repository.dart b/lib/arns/domain/arns_repository.dart index ef6f53b0d..9895fc568 100644 --- a/lib/arns/domain/arns_repository.dart +++ b/lib/arns/domain/arns_repository.dart @@ -35,6 +35,7 @@ abstract class ARNSRepository { Future waitForARNSRecordsToUpdate(); Future getUndernameByDomainAndName( String domain, String name); + Future> getARNSNameModelsForWallet(String address); factory ARNSRepository({ required ArioSDK sdk, @@ -393,6 +394,12 @@ class _ARNSRepository implements ARNSRepository { return undername; } + + @override + Future> getARNSNameModelsForWallet( + String address) async { + return _sdk.getArNSNames(address); + } } AntRecord toAntRecordFromSDK(sdk.ANTRecord record) { diff --git a/lib/arns/presentation/assign_name_bloc/assign_name_bloc.dart b/lib/arns/presentation/assign_name_bloc/assign_name_bloc.dart index ecc369cf3..fddf9d727 100644 --- a/lib/arns/presentation/assign_name_bloc/assign_name_bloc.dart +++ b/lib/arns/presentation/assign_name_bloc/assign_name_bloc.dart @@ -14,7 +14,8 @@ class AssignNameBloc extends Bloc { final ARNSRepository _arnsRepository; final ArDriveAuth _auth; ARNSUndername? _selectedUndername; - ANTRecord? _selectedANTRecord; + // TODO: remove this later + ArNSNameModel? _selectedNameModel; AssignNameBloc({ required ArDriveAuth auth, @@ -32,10 +33,19 @@ class AssignNameBloc extends Bloc { final names = await _arnsRepository.getAntRecordsForWallet(walletAddress!); + final nameModels = + await _arnsRepository.getARNSNameModelsForWallet(walletAddress); + + for (var nameModel in nameModels) { + logger.i('Name model: ${nameModel.toString()}'); + } + if (names.isEmpty) { emit(AssignNameEmptyState()); } else { - emit(NamesLoaded(names: names)); + emit(NamesLoaded( + nameModels: nameModels, + )); } } catch (e) { logger.e('Failed to load ArNS names', e); @@ -44,31 +54,35 @@ class AssignNameBloc extends Bloc { }); on((event, emit) async { - _selectedANTRecord = event.name; - + _selectedNameModel = event.nameModel; if (state is NamesLoaded) { emit( (state as NamesLoaded).copyWith( - selectedName: event.name, + selectedName: event.nameModel, ), ); } if (state is UndernamesLoaded) { emit( NamesLoaded( - names: (state as UndernamesLoaded).names, - selectedName: _selectedANTRecord), + nameModels: (state as UndernamesLoaded).nameModels, + selectedName: _selectedNameModel, + ), ); } }); on( (event, emit) async { - final names = (state as NamesLoaded).names; + final names = (state as NamesLoaded).nameModels; emit(LoadingUndernames()); - final undernames = - await _arnsRepository.getARNSUndernames(_selectedANTRecord!); + final undernames = await _arnsRepository.getARNSUndernames( + ANTRecord( + domain: _selectedNameModel!.name, + processId: _selectedNameModel!.processId, + ), + ); if (undernames.length > 1) { undernames.removeWhere((element) => element.name == '@'); @@ -76,8 +90,8 @@ class AssignNameBloc extends Bloc { emit( UndernamesLoaded( - selectedName: _selectedANTRecord!, - names: names, + nameModels: names, + selectedName: _selectedNameModel!, undernames: undernames, selectedUndername: null, ), @@ -111,7 +125,7 @@ class AssignNameBloc extends Bloc { name: '@', record: ARNSRecord( transactionId: fileDataTableItem.dataTxId, ttlSeconds: 3600), - domain: _selectedANTRecord!.domain, + domain: _selectedNameModel!.name, ); } else { undername = ARNSUndername( @@ -120,7 +134,7 @@ class AssignNameBloc extends Bloc { transactionId: fileDataTableItem.dataTxId, ttlSeconds: 3600, ), - domain: _selectedANTRecord!.domain, + domain: _selectedNameModel!.name, ); } @@ -128,11 +142,11 @@ class AssignNameBloc extends Bloc { undername: undername, fileId: fileDataTableItem.fileId, driveId: fileDataTableItem.driveId, - processId: _selectedANTRecord!.processId, + processId: _selectedNameModel!.processId, ); final (address, arAddress) = getAddressesFromArns( - domain: _selectedANTRecord!.domain, + domain: _selectedNameModel!.name, undername: _selectedUndername?.name, ); @@ -146,9 +160,21 @@ class AssignNameBloc extends Bloc { } }); + on((event, emit) async { + final (address, arAddress) = getAddressesFromArns( + domain: event.undername.domain, + undername: event.undername.name, + ); + + emit(NameAssignedWithSuccess( + address: address, + arAddress: arAddress, + )); + }); + on((event, emit) async { emit(SelectionConfirmed( - selectedName: _selectedANTRecord!, + selectedName: _selectedNameModel!, selectedUndername: _selectedUndername, )); }); diff --git a/lib/arns/presentation/assign_name_bloc/assign_name_event.dart b/lib/arns/presentation/assign_name_bloc/assign_name_event.dart index 369f23dc6..e065f9a89 100644 --- a/lib/arns/presentation/assign_name_bloc/assign_name_event.dart +++ b/lib/arns/presentation/assign_name_bloc/assign_name_event.dart @@ -18,12 +18,11 @@ final class LoadNames extends AssignNameEvent { final class CloseAssignName extends AssignNameEvent {} final class SelectName extends AssignNameEvent { - final ANTRecord name; - - const SelectName(this.name); + final ArNSNameModel nameModel; + const SelectName(this.nameModel); @override - List get props => [name]; + List get props => [nameModel]; } final class LoadUndernames extends AssignNameEvent { @@ -47,3 +46,13 @@ final class SelectUndername extends AssignNameEvent { final class ConfirmSelectionAndUpload extends AssignNameEvent {} final class ConfirmSelection extends AssignNameEvent {} + +final class ShowSuccessModal extends AssignNameEvent { + final ARNSUndername undername; + + const ShowSuccessModal({required this.undername}); + + @override + List get props => [undername]; +} +// diff --git a/lib/arns/presentation/assign_name_bloc/assign_name_state.dart b/lib/arns/presentation/assign_name_bloc/assign_name_state.dart index 10b609dcf..e2e255213 100644 --- a/lib/arns/presentation/assign_name_bloc/assign_name_state.dart +++ b/lib/arns/presentation/assign_name_bloc/assign_name_state.dart @@ -12,20 +12,20 @@ final class AssignNameInitial extends AssignNameState {} final class LoadingNames extends AssignNameState {} final class NamesLoaded extends AssignNameState { - final List names; - final ANTRecord? selectedName; + final List nameModels; + final ArNSNameModel? selectedName; - const NamesLoaded({required this.names, this.selectedName}); + const NamesLoaded({required this.nameModels, this.selectedName}); @override - List get props => [names, selectedName]; + List get props => [nameModels, selectedName]; NamesLoaded copyWith({ - List? names, - ANTRecord? selectedName, + List? nameModels, + ArNSNameModel? selectedName, }) { return NamesLoaded( - names: names ?? this.names, + nameModels: nameModels ?? this.nameModels, selectedName: selectedName ?? this.selectedName, ); } @@ -34,13 +34,13 @@ final class NamesLoaded extends AssignNameState { final class AssignNameEmptyState extends AssignNameState {} final class UndernamesLoaded extends AssignNameState { - final List names; - final ANTRecord selectedName; + final List nameModels; final List undernames; final ARNSUndername? selectedUndername; + final ArNSNameModel? selectedName; const UndernamesLoaded({ - required this.names, + required this.nameModels, required this.undernames, required this.selectedUndername, required this.selectedName, @@ -48,20 +48,20 @@ final class UndernamesLoaded extends AssignNameState { @override List get props => [ - names, + nameModels, selectedName, undernames, selectedUndername, ]; UndernamesLoaded copyWith({ - List? names, - ANTRecord? selectedName, List? undernames, ARNSUndername? selectedUndername, + List? nameModels, + ArNSNameModel? selectedName, }) { return UndernamesLoaded( - names: names ?? this.names, + nameModels: nameModels ?? this.nameModels, selectedName: selectedName ?? this.selectedName, undernames: undernames ?? this.undernames, selectedUndername: selectedUndername ?? this.selectedUndername, @@ -80,7 +80,7 @@ final class NameAssignedWithSuccess extends AssignNameState { } final class SelectionConfirmed extends AssignNameState { - final ANTRecord selectedName; + final ArNSNameModel selectedName; final ARNSUndername? selectedUndername; const SelectionConfirmed({ diff --git a/lib/arns/presentation/assign_name_modal.dart b/lib/arns/presentation/assign_name_modal.dart index 26d04c4aa..9e99e960c 100644 --- a/lib/arns/presentation/assign_name_modal.dart +++ b/lib/arns/presentation/assign_name_modal.dart @@ -2,6 +2,7 @@ import 'package:ardrive/arns/domain/arns_repository.dart'; import 'package:ardrive/arns/presentation/assign_name_bloc/assign_name_bloc.dart'; +import 'package:ardrive/arns/presentation/create_undername.dart'; import 'package:ardrive/authentication/ardrive_auth.dart'; import 'package:ardrive/blocs/blocs.dart'; import 'package:ardrive/blocs/drive_detail/drive_detail_cubit.dart'; @@ -188,9 +189,9 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> { const SizedBox( height: 16, ), - _NameSelectorDropdown( + _NameSelectorDropdown( label: 'ArNS name', - names: state.names, + names: state.nameModels, hintText: 'Choose ArNS name', selectedName: state.selectedName, onSelected: (name) { @@ -238,10 +239,10 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> { const SizedBox( height: 16, ), - _NameSelectorDropdown( + _NameSelectorDropdown( selectedName: state.selectedName, label: 'ArNS name', - names: state.names, + names: state.nameModels, hintText: 'Choose ArNS name', onSelected: (name) { context.read().add(SelectName(name)); @@ -264,6 +265,40 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> { .add(SelectUndername(undername: name)); }, ), + // or add a new name + if (state.selectedName != null) ...[ + const SizedBox(height: 16), + Align( + alignment: Alignment.centerLeft, + child: + Text('or', style: typography.paragraphNormal()), + ), + const SizedBox(height: 16), + ArDriveButtonNew( + text: state.selectedName!.records >= + state.selectedName!.undernameLimit + ? 'You cant create more undernames ${state.selectedName!.records} of ${state.selectedName!.undernameLimit} in use' + : 'Add new undername ${state.selectedName!.records} of ${state.selectedName!.undernameLimit} in use', + onPressed: () { + showArDriveDialog( + context, + content: BlocProvider( + create: (context) => + this.context.read(), + child: CreateUndernameModal( + nameModel: state.selectedName!, + driveId: widget.file!.driveId, + fileId: widget.file!.id, + transactionId: widget.file!.dataTxId, + ), + ), + ); + }, + typography: typography, + isDisabled: state.selectedName!.records >= + state.selectedName!.undernameLimit, + ), + ], ], ), ); @@ -326,7 +361,7 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> { ModalAction( action: () { Navigator.of(context).pop(); - }, + }, title: 'Cancel', ), ModalAction( @@ -547,8 +582,8 @@ class __NameSelectorDropdownState extends State<_NameSelectorDropdown> { String _getName(T item) { String name; - if (item is ANTRecord) { - name = item.domain; + if (item is ArNSNameModel) { + name = item.name; } else if (item is ARNSUndername) { name = item.name; } else { diff --git a/lib/arns/presentation/create_undername.dart b/lib/arns/presentation/create_undername.dart new file mode 100644 index 000000000..49dc5eef6 --- /dev/null +++ b/lib/arns/presentation/create_undername.dart @@ -0,0 +1,129 @@ +import 'package:ardrive/arns/domain/arns_repository.dart'; +import 'package:ardrive/arns/presentation/assign_name_bloc/assign_name_bloc.dart'; +import 'package:ardrive/arns/presentation/create_undername/create_undername_bloc.dart'; +import 'package:ardrive/theme/theme.dart'; +import 'package:ardrive_ui/ardrive_ui.dart'; +import 'package:ario_sdk/ario_sdk.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class CreateUndernameModal extends StatelessWidget { + const CreateUndernameModal({ + super.key, + required this.nameModel, + required this.driveId, + required this.fileId, + required this.transactionId, + }); + + final ArNSNameModel nameModel; + final String driveId; + final String fileId; + final String transactionId; + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => CreateUndernameBloc( + context.read(), + nameModel, + driveId, + fileId, + transactionId, + ), + child: CreateUndernameView(), + ); + } +} + +class CreateUndernameView extends StatefulWidget { + const CreateUndernameView({super.key}); + + @override + State createState() => _CreateUndernameViewState(); +} + +class _CreateUndernameViewState extends State { + final controller = TextEditingController(); + + @override + void initState() { + super.initState(); + controller.addListener(() { + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + return ArDriveStandardModalNew( + width: kMediumDialogWidth, + title: 'Create Undername', + content: BlocConsumer( + listener: (context, state) { + if (state is CreateUndernameSuccess) { + context.read().add( + ShowSuccessModal( + undername: state.undername, + ), + ); + Navigator.pop(context); + } + }, + builder: (context, state) { + final typography = ArDriveTypographyNew.of(context); + if (state is CreateUndernameSuccess) { + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text('Undername created successfully', + style: typography.paragraphNormal()), + ); + } + + if (state is CreateUndernameLoading) { + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text('Creating undername...', + style: typography.paragraphNormal()), + ); + } + + return CreateUndernameForm(onChanged: (text) { + controller.text = text; + }); + }, + ), + actions: [ + ModalAction( + action: () { + Navigator.pop(context); + }, + title: 'Cancel', + ), + ModalAction( + isEnable: controller.text.isNotEmpty, + action: () { + context + .read() + .add(CreateNewUndername(controller.text)); + }, + title: 'Create', + ), + ], + ); + } +} + +class CreateUndernameForm extends StatelessWidget { + const CreateUndernameForm({super.key, required this.onChanged}); + + final Function(String) onChanged; + + @override + Widget build(BuildContext context) { + return ArDriveTextFieldNew( + label: 'Undername', + hintText: 'Enter your undername', + onChanged: onChanged, + ); + } +} diff --git a/lib/arns/presentation/create_undername/create_undername_bloc.dart b/lib/arns/presentation/create_undername/create_undername_bloc.dart new file mode 100644 index 000000000..39ab57660 --- /dev/null +++ b/lib/arns/presentation/create_undername/create_undername_bloc.dart @@ -0,0 +1,51 @@ +import 'package:ardrive/arns/domain/arns_repository.dart'; +import 'package:ardrive/utils/logger.dart'; +import 'package:ario_sdk/ario_sdk.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'create_undername_event.dart'; +part 'create_undername_state.dart'; + +class CreateUndernameBloc + extends Bloc { + final ARNSRepository _arnsRepository; + final ArNSNameModel _nameModel; + final String driveId; + final String fileId; + final String transactionId; + CreateUndernameBloc( + this._arnsRepository, + this._nameModel, + this.driveId, + this.fileId, + this.transactionId, + ) : super(CreateUndernameInitial()) { + on((event, emit) async { + if (event is CreateNewUndername) { + emit(CreateUndernameLoading()); + + final ARNSUndername undername = ARNSUndername( + name: event.name, + record: ARNSRecord( + transactionId: transactionId, + ttlSeconds: 3600, + ), + domain: _nameModel.name, + ); + + logger.d('Process ID: ${_nameModel.processId}'); + await _arnsRepository.setUndernamesToFile( + undername: undername, + driveId: driveId, + fileId: fileId, + processId: _nameModel.processId, + ); + + logger.d('Creating new undername: ${event.name}'); + + emit(CreateUndernameSuccess(undername: undername)); + } + }); + } +} diff --git a/lib/arns/presentation/create_undername/create_undername_event.dart b/lib/arns/presentation/create_undername/create_undername_event.dart new file mode 100644 index 000000000..f47b154dd --- /dev/null +++ b/lib/arns/presentation/create_undername/create_undername_event.dart @@ -0,0 +1,18 @@ +part of 'create_undername_bloc.dart'; + +sealed class CreateUndernameEvent extends Equatable { + const CreateUndernameEvent(); + + @override + List get props => []; +} + +final class CreateNewUndername extends CreateUndernameEvent { + final String name; + + const CreateNewUndername(this.name); + + @override + List get props => [name]; +} +// diff --git a/lib/arns/presentation/create_undername/create_undername_state.dart b/lib/arns/presentation/create_undername/create_undername_state.dart new file mode 100644 index 000000000..bbae878f7 --- /dev/null +++ b/lib/arns/presentation/create_undername/create_undername_state.dart @@ -0,0 +1,26 @@ +part of 'create_undername_bloc.dart'; + +sealed class CreateUndernameState extends Equatable { + const CreateUndernameState(); + + @override + List get props => []; +} + +final class CreateUndernameInitial extends CreateUndernameState {} + +final class CreateUndernameLoading extends CreateUndernameState {} + +final class CreateUndernameSuccess extends CreateUndernameState { + final ARNSUndername undername; + + const CreateUndernameSuccess({required this.undername}); + + @override + List get props => [undername]; +} + +final class CreateUndernameFailure extends CreateUndernameState { + @override + List get props => []; +} diff --git a/lib/components/create_manifest_form.dart b/lib/components/create_manifest_form.dart index 9e19d676d..c6a037b04 100644 --- a/lib/components/create_manifest_form.dart +++ b/lib/components/create_manifest_form.dart @@ -325,10 +325,11 @@ class _CreateManifestFormState extends State { customLoadingText: 'Fetching ArNS names...', customNameSelectionTitle: 'Assign ArNS Name to New Manifest', onSelectionConfirmed: (selection) { - context.read().selectArns( - selection.selectedName, - selection.selectedUndername, - ); + // TODO: RE-ENABLE THIS + // context.read().selectArns( + // selection.selectedName, + // selection.selectedUndername, + // ); }, ); } diff --git a/lib/components/upload_form.dart b/lib/components/upload_form.dart index 9db202434..816e3a1e1 100644 --- a/lib/components/upload_form.dart +++ b/lib/components/upload_form.dart @@ -336,10 +336,12 @@ class _UploadFormState extends State { driveDetailCubit: widget.driveDetailCubit, justSelectName: true, onSelectionConfirmed: (name) { - context.read().selectUndernameWithLicense( - antRecord: name.selectedName, - undername: name.selectedUndername, - ); + // TODO: RE-ENABLE THIS + + // context.read().selectUndernameWithLicense( + // antRecord: name.selectedName, + // undername: name.selectedUndername, + // ); }, canClose: false, onEmptySelection: (emptySelection) { @@ -1746,9 +1748,10 @@ class _UploadReadyWidget extends StatelessWidget { driveDetailCubit: driveDetailCubit, justSelectName: true, onSelectionConfirmed: (name) { - context - .read() - .selectUndername(name.selectedName, name.selectedUndername); + // TODO: RE-ENABLE THIS + // context + // .read() + // .selectUndername(name.selectedName, name.selectedUndername); }, canClose: false, onEmptySelection: (emptySelection) { diff --git a/packages/ario_sdk/lib/src/ario_sdk.dart b/packages/ario_sdk/lib/src/ario_sdk.dart index 8e37a375b..f40095fe0 100644 --- a/packages/ario_sdk/lib/src/ario_sdk.dart +++ b/packages/ario_sdk/lib/src/ario_sdk.dart @@ -1,7 +1,7 @@ library ario; import 'package:ario_sdk/ario_sdk.dart'; -import 'package:ario_sdk/src/models/response_object.dart'; +import 'package:ario_sdk/src/models/arns_name_model.dart'; abstract class ArioSDK { /// Get the list of available gateways @@ -27,4 +27,6 @@ abstract class ArioSDK { required String domain, String undername = '@', }); + + Future> getArNSNames(String address); } diff --git a/packages/ario_sdk/lib/src/implementations/ario_sdk_web.dart b/packages/ario_sdk/lib/src/implementations/ario_sdk_web.dart index 1e6cbed23..cc5a7f62f 100644 --- a/packages/ario_sdk/lib/src/implementations/ario_sdk_web.dart +++ b/packages/ario_sdk/lib/src/implementations/ario_sdk_web.dart @@ -8,7 +8,6 @@ import 'dart:js_util'; import 'package:ario_sdk/ario_sdk.dart'; import 'package:ario_sdk/src/exceptions.dart'; -import 'package:ario_sdk/src/models/response_object.dart'; import 'package:js/js.dart'; class ArioSDKWeb implements ArioSDK { @@ -97,6 +96,33 @@ class ArioSDKWeb implements ArioSDK { return _setARNSImpl('', arnsUndername, true); } + + @override + Future> getArNSNames(String address) async { + final processes = await _getARNSRecordsForWalletImpl(address); + + List names = []; + + for (var e in processes) { + final name = e.names[e.names.keys.first]; + final undernameLimit = name?.undernameLimit; + + if (undernameLimit == null) { + throw Exception('Under name limit is null'); + } + + e.state.records.removeWhere((key, value) => key == '@'); + + names.add(ArNSNameModel( + name: e.names.keys.first, + processId: e.names.keys.first, + records: e.state.records.length, + undernameLimit: undernameLimit, + )); + } + + return names; + } } @JS('setARNS') diff --git a/packages/ario_sdk/lib/src/implementations/ario_sdk_web_stub.dart b/packages/ario_sdk/lib/src/implementations/ario_sdk_web_stub.dart index 23d26c7bc..d06468793 100644 --- a/packages/ario_sdk/lib/src/implementations/ario_sdk_web_stub.dart +++ b/packages/ario_sdk/lib/src/implementations/ario_sdk_web_stub.dart @@ -1,4 +1,5 @@ import 'package:ario_sdk/ario_sdk.dart'; +import 'package:ario_sdk/src/models/arns_name_model.dart'; import 'package:ario_sdk/src/models/response_object.dart'; class ArioSDKWeb implements ArioSDK { @@ -43,4 +44,10 @@ class ArioSDKWeb implements ArioSDK { // TODO: implement setUndernameWithArConnect throw UnimplementedError(); } + + @override + Future> getArNSNames(String address) { + // TODO: implement getArNSNames + throw UnimplementedError(); + } } diff --git a/packages/ario_sdk/lib/src/models/arns_name_model.dart b/packages/ario_sdk/lib/src/models/arns_name_model.dart new file mode 100644 index 000000000..0d41b5c92 --- /dev/null +++ b/packages/ario_sdk/lib/src/models/arns_name_model.dart @@ -0,0 +1,24 @@ +import 'package:equatable/equatable.dart'; + +class ArNSNameModel extends Equatable { + // TODO: maybe a list of records + final String name; + final String processId; + final int records; + final int undernameLimit; + + const ArNSNameModel({ + required this.name, + required this.processId, + required this.records, + required this.undernameLimit, + }); + + @override + List get props => [name, processId, records, undernameLimit]; + + @override + String toString() { + return 'ArNSNameModel(name: $name, processId: $processId, records: $records, undernameLimit: $undernameLimit)'; + } +} diff --git a/packages/ario_sdk/lib/src/models/models.dart b/packages/ario_sdk/lib/src/models/models.dart index d625c2979..0e65d719f 100644 --- a/packages/ario_sdk/lib/src/models/models.dart +++ b/packages/ario_sdk/lib/src/models/models.dart @@ -1,4 +1,6 @@ export 'ant_record.dart'; +export 'arns_name_model.dart'; export 'arns_record.dart'; export 'gateway.dart'; +export 'response_object.dart'; export 'undername.dart'; diff --git a/packages/ario_sdk/lib/src/models/response_object.dart b/packages/ario_sdk/lib/src/models/response_object.dart index 8555bcc9f..cf2cedd81 100644 --- a/packages/ario_sdk/lib/src/models/response_object.dart +++ b/packages/ario_sdk/lib/src/models/response_object.dart @@ -18,14 +18,14 @@ class ResponseObject { } class ARNSProcessData { - final State state; + final ProcessState state; final Map names; ARNSProcessData({required this.state, required this.names}); factory ARNSProcessData.fromJson(Map json) { return ARNSProcessData( - state: State.fromJson(json['state']), + state: ProcessState.fromJson(json['state']), names: (json['names'] as Map).map( (key, value) => MapEntry(key, ARNSName.fromJson(value)), ), @@ -40,7 +40,7 @@ class ARNSProcessData { } } -class State { +class ProcessState { final int totalSupply; final String? sourceCodeTxId; final Map balances; @@ -53,7 +53,7 @@ class State { final String name; final String owner; - State({ + ProcessState({ required this.totalSupply, this.sourceCodeTxId, required this.balances, @@ -67,8 +67,8 @@ class State { required this.owner, }); - factory State.fromJson(Map json) { - return State( + factory ProcessState.fromJson(Map json) { + return ProcessState( totalSupply: json['TotalSupply'], sourceCodeTxId: json['Source-Code-TX-ID'], balances: Map.from(json['Balances']),