From d18eb5990303e5fa53b3a6792684292df84aaa3f Mon Sep 17 00:00:00 2001 From: Simone Sestito Date: Sat, 20 Jan 2024 10:13:13 +0100 Subject: [PATCH] React to Tor/Ipfs overwritten events in my domains list --- lib/bloc/domains/domains_bloc.dart | 15 ++++++++ lib/bloc/global_errors/banner.dart | 6 +++ lib/bloc/global_errors/global_events.dart | 3 ++ lib/contracts/events.dart | 29 ++++++++++++++ web/js/geth_domains.js | 46 +++++++++++++---------- 5 files changed, 79 insertions(+), 20 deletions(-) diff --git a/lib/bloc/domains/domains_bloc.dart b/lib/bloc/domains/domains_bloc.dart index dc11adc..f5cc202 100644 --- a/lib/bloc/domains/domains_bloc.dart +++ b/lib/bloc/domains/domains_bloc.dart @@ -20,6 +20,7 @@ class DomainsBloc extends Bloc { final SellingRepository sellingRepository; final GlobalErrorsSink globalErrorsSink; final GlobalEventsSink globalEventsSink; + String? currentUser; DomainsBloc({ required this.domainsRepository, @@ -41,8 +42,10 @@ class DomainsBloc extends Bloc { authStateChanges.listen((state) { debugPrint('DomainsBloc: authStateChanges.listen: $state'); if (state is AuthLoggedIn) { + currentUser = state.account.address; add(const LoadDomainsEvent()); } else { + currentUser = null; add(const _UpdateDomainsEvent(domains: null)); } }); @@ -61,6 +64,15 @@ class DomainsBloc extends Bloc { debugPrint('DomainsBloc: globalEventsSink.domainListings.listen: $event'); add(DomainListedForSaleEvent(event.domainName, event.price)); }); + + // Listen to the global events of domain edits + // and react to my domains only + globalEventsSink.domainEdits.map(_removeGethSuffix).listen((event) { + if (event.owner == currentUser) { + debugPrint('DomainsBloc: globalEventsSink.domainEdits.listen: $event'); + add(const LoadDomainsEvent()); + } + }); } FutureOr _onLoadDomainsEvent( @@ -291,6 +303,9 @@ class DomainsBloc extends Bloc { Web3DomainTransfer _ => event.copyWith( domainName: removeDomainName(event.domainName), ), + Web3DomainEdited _ => event.copyWith( + domainName: removeDomainName(event.domainName), + ), _ => throw UnimplementedError('[DomainsBloc] Unknown event type: $event'), } as T; } diff --git a/lib/bloc/global_errors/banner.dart b/lib/bloc/global_errors/banner.dart index ff8d1cd..a719030 100644 --- a/lib/bloc/global_errors/banner.dart +++ b/lib/bloc/global_errors/banner.dart @@ -165,6 +165,12 @@ class _GlobalErrorsBannerState extends State { return const SizedBox.shrink(); } + if (notice is Web3DomainEdited && notice.owner != authenticatedAccount) { + // Do not show banners for domain edited events, + // if the domain is not owned by the user + return const SizedBox.shrink(); + } + return BannerCard( color: color, icon: icon, diff --git a/lib/bloc/global_errors/global_events.dart b/lib/bloc/global_errors/global_events.dart index 2a19a55..45db6d0 100644 --- a/lib/bloc/global_errors/global_events.dart +++ b/lib/bloc/global_errors/global_events.dart @@ -39,6 +39,9 @@ class GlobalEventsSink { Stream get domainPurchases => _getWeb3Events(); + Stream get domainEdits => + _getWeb3Events(); + void addWeb3Event(Web3Event event) { debugPrint('[Web3Event] $event'); _web3ErrorsStreamController.add(event); diff --git a/lib/contracts/events.dart b/lib/contracts/events.dart index 82f0a6e..a1f6d99 100644 --- a/lib/contracts/events.dart +++ b/lib/contracts/events.dart @@ -35,6 +35,7 @@ sealed class Web3Event extends Web3Notice { 'domainListingForSale' => Web3DomainListingForSale.fromJson(message), 'domainSold' => Web3DomainSold.fromJson(message), 'royaltiesPaid' => Web3RoyaltiesPaid.fromJson(message), + 'domainPointerOverwritten' => Web3DomainEdited.fromJson(message), _ => throw Exception('Unknown Web3Event tag: $tag'), }; } @@ -212,3 +213,31 @@ class Web3RoyaltiesPaid extends Web3DomainEvent { ); } } + +class Web3DomainEdited extends Web3DomainEvent { + final String owner; + + const Web3DomainEdited({ + required this.owner, + required String domainName, + }) : super(domainName, 'Domain $domainName edited'); + + factory Web3DomainEdited.fromJson(String json) { + const domainEncoder = DomainEncoder( + domainSuffix: DomainInputValidator.domainSuffix, + ); + final data = jsonDecode(json); + final domainBytes = receiveUint8ListFromHex(data['domainBytes']); + + return Web3DomainEdited( + owner: data['owner'], + domainName: + domainEncoder.decode(domainBytes) + DomainInputValidator.domainSuffix, + ); + } + + Web3DomainEdited copyWith({String? domainName}) => Web3DomainEdited( + owner: owner, + domainName: domainName ?? this.domainName, + ); +} diff --git a/web/js/geth_domains.js b/web/js/geth_domains.js index 4de829d..d8838ae 100644 --- a/web/js/geth_domains.js +++ b/web/js/geth_domains.js @@ -1279,27 +1279,22 @@ let domains_received_event_emitter = null; let domains_listing_event_emitter = null; let domains_selling_event_emitter = null; let domains_royalties_event_emitter = null; +let domains_ipfs_overwritten_event_emitter = null; +let domains_tor_overwritten_event_emitter = null; async function _initDomainsEvents() { - if (domains_sent_event_emitter !== null) { - domains_sent_event_emitter.removeAllListeners('data'); - domains_sent_event_emitter.removeAllListeners('error'); - } - if (domains_received_event_emitter !== null) { - domains_received_event_emitter.removeAllListeners('data'); - domains_received_event_emitter.removeAllListeners('error'); - } - if (domains_listing_event_emitter !== null) { - domains_listing_event_emitter.removeAllListeners('data'); - domains_listing_event_emitter.removeAllListeners('error'); - } - if (domains_selling_event_emitter !== null) { - domains_selling_event_emitter.removeAllListeners('data'); - domains_selling_event_emitter.removeAllListeners('error'); - } - if (domains_royalties_event_emitter !== null) { - domains_royalties_event_emitter.removeAllListeners('data'); - domains_royalties_event_emitter.removeAllListeners('error'); - } + // Remove all the previous listeners + [ + domains_sent_event_emitter, + domains_received_event_emitter, + domains_listing_event_emitter, + domains_selling_event_emitter, + domains_royalties_event_emitter, + domains_ipfs_overwritten_event_emitter, + domains_tor_overwritten_event_emitter, + ].filter((x) => x !== null).forEach((x) => { + x.removeAllListeners('data'); + x.removeAllListeners('error'); + }); const [contract, user] = await _initializeGethDomainsContract(); if (user === null) { @@ -1358,5 +1353,16 @@ async function _initDomainsEvents() { royaltiesAmount: event.returnValues.royaltiesAmount, })); }).on('error', _onError); + + // Subscribe to IpfsOverwritten and TorOverwritten events + const _onOverwrittenEvent = function(event) { + console.log(event); + web3EventsSink('domainPointerOverwritten', JSON.stringify({ + domainBytes: event.returnValues.domain, + owner: event.returnValues.owner, + })); + }; + domains_ipfs_overwritten_event_emitter = contract.events.IpfsOverwritten().on('data', _onOverwrittenEvent).on('error', _onError); + domains_tor_overwritten_event_emitter = contract.events.TorOverwritten().on('data', _onOverwrittenEvent).on('error', _onError); } _initDomainsEvents().catch(console.error); \ No newline at end of file