diff --git a/src/config/tdb/migrations/LoadingJob_SocialGraph.gsql b/src/config/tdb/migrations/LoadingJob_SocialGraph.gsql index 2403d0b..4709c37 100644 --- a/src/config/tdb/migrations/LoadingJob_SocialGraph.gsql +++ b/src/config/tdb/migrations/LoadingJob_SocialGraph.gsql @@ -494,11 +494,11 @@ CREATE OR REPLACE QUERY delete_graph_inner_connection(VERTEX p, INT // DELETE e FROM vertex2delete:s-((Hold_Contract>):e)-Contracts:c; // DELETE e FROM vertex2delete:s-((Reverse_Resolve_Contract>):e)-Contracts:c; // DELETE e FROM vertex2delete:s-(( p, CREATE OR REPLACE QUERY delete_domain_collection(VERTEX p) FOR GRAPH SocialGraph { vertex2delete (DomainCollection) = {p}; - DELETE e FROM vertex2delete:s-((PartOfCollection>):e)-Identities:tgt; - DELETE s FROM vertex2delete:s; + DELETE e FROM vertex2delete:s-((PartOfCollection>):e)-Identities:tgt WHERE tgt.platform != "basenames"; } CREATE OR REPLACE QUERY clear_domain_search_cache() FOR GRAPH SocialGraph { @@ -541,7 +540,7 @@ CREATE OR REPLACE QUERY domain_available_search(STRING id) FOR GRAPH SocialGraph CREATE OR REPLACE QUERY domain_available_search_draft(SET names, SET ens_names) FOR GRAPH SocialGraph { TYPEDEF TUPLE< STRING system, STRING name, DATETIME expired_at > DomainResult; - ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ens", "sns", "genome", "clusters"]; + ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ens", "sns", "genome", "clusters", "basenames"]; SetAccum @@domain_result; owner = SELECT s FROM Identities:s-((Hold_Identity>):e)-Identities:v @@ -579,7 +578,7 @@ CREATE OR REPLACE QUERY find_identity_graph_resolve(STRING platform, STRING iden PRINT seed; graph_id = @@minUpdateTime.id; - ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters"]; + ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters", "basenames"]; ListAccum @@edge_type = ["Proof_Forward", "Proof_Backward", "Hold_Identity", "Resolve", "Reverse_Resolve"]; vset = SELECT v FROM Identities:v-((PartOfIdentitiesGraph>):e)-identities_graph LIMIT 500; @@ -625,7 +624,7 @@ CREATE OR REPLACE QUERY find_expand_identity(STRING platform, STRING identity) F SetAccum
@owner_address; SetAccum
@resolve_address; - ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters"]; + ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters", "basenames"]; IF @@domainSystems.contains(platform) == TRUE THEN tmp = SELECT domain FROM seed:domain-(( @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters"]; + ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters", "basenames"]; ListAccum @@edge_type = ["Proof_Forward", "Proof_Backward", "Hold_Identity", "Resolve", "Reverse_Resolve"]; IF reverse_flag == 1 THEN @@ -675,21 +674,21 @@ CREATE OR REPLACE QUERY find_identity_graph(STRING p, INT reverse_flag=0) FOR GR tmp2 = SELECT v1 FROM vset:v1-(():e1)-vset:i-((Resolve>):e2)-vset:v2 - WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" + WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" AND i.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, i, e1.source, "Hold"), i.@owner_address += Address(v1.platform, v1.identity), i.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp5 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" + WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" AND v2.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, v2, e1.source, "Hold"), v2.@owner_address += Address(v1.platform, v1.identity), v1.@degree += 1, v2.@degree += 1; tmp3 = SELECT v1 FROM vset:v1-((Resolve>):r)-vset:v2 - WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" + WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" OR v1.platform == "basenames" ACCUM @@edges += IdentityConnection(v1, v2, r.source, "Resolve"), v1.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp3_1 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" + WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" OR v2.platform == "basenames" ACCUM v2.@owner_address += Address(v1.platform, v1.identity); tmp6 = SELECT v1 FROM vset:v1-((Reverse_Resolve>):e1)-vset:v2 @@ -706,21 +705,21 @@ CREATE OR REPLACE QUERY find_identity_graph(STRING p, INT reverse_flag=0) FOR GR tmp2 = SELECT v1 FROM vset:v1-(():e1)-vset:i-((Resolve>):e2)-vset:v2 - WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" + WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" AND i.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, i, e1.source, "Hold"), i.@owner_address += Address(v1.platform, v1.identity), i.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp5 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" + WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" AND v2.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, v2, e1.source, "Hold"), v2.@owner_address += Address(v1.platform, v1.identity), v1.@degree += 1, v2.@degree += 1; tmp3 = SELECT v1 FROM vset:v1-((Resolve>):r)-vset:v2 - WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" + WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" OR v1.platform == "basenames" ACCUM @@edges += IdentityConnection(v1, v2, r.source, "Resolve"), v1.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp3_1 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" + WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" OR v2.platform == "basenames" ACCUM v2.@owner_address += Address(v1.platform, v1.identity); tmp6 = SELECT v1 FROM vset:v1-((Reverse_Resolve>):e1)-vset:v2 ACCUM @@edges += IdentityConnection(v1, v2, e1.source, "Reverse_Resolve"), v1.@degree += 1, v2.@degree += 1; @@ -735,21 +734,21 @@ CREATE OR REPLACE QUERY find_identity_graph(STRING p, INT reverse_flag=0) FOR GR tmp2 = SELECT v1 FROM vset:v1-(():e1)-vset:i-((Resolve>):e2)-vset:v2 - WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" + WHERE i.platform != "genome" AND i.platform != "ens" AND i.platform != "sns" AND i.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, i, e1.source, "Hold"), i.@owner_address += Address(v1.platform, v1.identity), i.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp5 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" + WHERE v2.platform != "genome" AND v2.platform != "ens" AND v2.platform != "sns" AND v2.platform != "basenames" ACCUM @@edges += IdentityConnection(v1, v2, e1.source, "Hold"), v2.@owner_address += Address(v1.platform, v1.identity), v1.@degree += 1, v2.@degree += 1; tmp3 = SELECT v1 FROM vset:v1-((Resolve>):r)-vset:v2 - WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" + WHERE v1.platform == "genome" OR v1.platform == "ens" OR v1.platform == "sns" OR v1.platform == "basenames" ACCUM @@edges += IdentityConnection(v1, v2, r.source, "Resolve"), v1.@resolve_address += Address(v2.platform, v2.identity), v1.@degree += 1, v2.@degree += 1; tmp3_1 = SELECT v1 FROM vset:v1-((Hold_Identity>):e1)-vset:v2 - WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" + WHERE v2.platform == "genome" OR v2.platform == "ens" OR v2.platform == "sns" OR v2.platform == "basenames" ACCUM v2.@owner_address += Address(v1.platform, v1.identity); tmp6 = SELECT v1 FROM vset:v1-((Reverse_Resolve>):e1)-vset:v2 @@ -791,7 +790,7 @@ CREATE OR REPLACE QUERY neighbors_with_source_reverse(VERTEX p, INT SetAccum @source_list; SetAccum @@edge_set; SetAccum> @@vertices; - ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters"]; + ListAccum @@domainSystems = ["dotbit", "lens", "unstoppabledomains", "space_id", "crossbell", "ENS", "ens", "sns", "genome", "clusters", "basenames"]; ##### Initialization ##### seed (Identities) = {p}; diff --git a/src/controller/tigergraphql/identity.rs b/src/controller/tigergraphql/identity.rs index b65a8e5..ee9086f 100644 --- a/src/controller/tigergraphql/identity.rs +++ b/src/controller/tigergraphql/identity.rs @@ -233,7 +233,14 @@ impl IdentityRecord { /// The expiry date for the domain, from either the registration, or the wrapped domain if PCC is burned async fn expired_at(&self) -> Option { - if !vec![Platform::Dotbit, Platform::ENS, Platform::Genome].contains(&self.platform) { + if !vec![ + Platform::Dotbit, + Platform::ENS, + Platform::Genome, + Platform::Basenames, + ] + .contains(&self.platform) + { return None; } self.expired_at.map(|dt| dt.and_utc().timestamp()) @@ -255,6 +262,7 @@ impl IdentityRecord { Platform::Solana, Platform::SNS, Platform::Genome, + Platform::Basenames, ] .contains(&self.platform) { @@ -275,6 +283,7 @@ impl IdentityRecord { Platform::ENS, Platform::SNS, Platform::Genome, + Platform::Basenames, ] .contains(&self.platform) { diff --git a/src/controller/tigergraphql/identity_graph.rs b/src/controller/tigergraphql/identity_graph.rs index 08c9e82..cea0855 100644 --- a/src/controller/tigergraphql/identity_graph.rs +++ b/src/controller/tigergraphql/identity_graph.rs @@ -140,7 +140,14 @@ impl ExpandIdentityRecord { /// The expiry date for the domain, from either the registration, or the wrapped domain if PCC is burned async fn expired_at(&self) -> Option { - if !vec![Platform::Dotbit, Platform::ENS, Platform::Genome].contains(&self.platform) { + if !vec![ + Platform::Dotbit, + Platform::ENS, + Platform::Genome, + Platform::Basenames, + ] + .contains(&self.platform) + { return None; } self.expired_at.map(|dt| dt.and_utc().timestamp()) @@ -162,6 +169,7 @@ impl ExpandIdentityRecord { Platform::Solana, Platform::SNS, Platform::Genome, + Platform::Basenames, ] .contains(&self.platform) { @@ -182,6 +190,7 @@ impl ExpandIdentityRecord { Platform::ENS, Platform::SNS, Platform::Genome, + Platform::Basenames, ] .contains(&self.platform) { diff --git a/src/tigergraph/vertex/domain_collection.rs b/src/tigergraph/vertex/domain_collection.rs index dd7d71a..4d88074 100644 --- a/src/tigergraph/vertex/domain_collection.rs +++ b/src/tigergraph/vertex/domain_collection.rs @@ -244,9 +244,10 @@ impl DomainCollection { Platform::ENS, Platform::Farcaster, Platform::Lens, - Platform::SNS, Platform::Clusters, + Platform::Basenames, Platform::UnstoppableDomains, + Platform::SNS, Platform::SpaceId, Platform::Dotbit, Platform::Crossbell, diff --git a/src/tigergraph/vertex/identity_graph.rs b/src/tigergraph/vertex/identity_graph.rs index 3a595e5..9fcce16 100644 --- a/src/tigergraph/vertex/identity_graph.rs +++ b/src/tigergraph/vertex/identity_graph.rs @@ -6,9 +6,10 @@ use crate::{ Attribute, BaseResponse, Graph, OpCode, Transfer, }, upstream::{Chain, DataSource, Platform}, - util::parse_body, + util::{naive_now, parse_body}, }; use async_trait::async_trait; +use chrono::Duration; use http::uri::InvalidUri; use hyper::{client::HttpConnector, Body, Client, Method}; use serde::de::{self, MapAccess, Visitor}; @@ -322,15 +323,35 @@ impl IdentityGraph { return Ok(None); // If vertices=1, it's isolated vertex } } else { - // filter out dataSource == "keybase" edges + // filter out dataSource == "basenames" edges let filter_edges: Vec = result .edges .clone() .into_iter() - .filter(|e| e.source != DataSource::Keybase.to_string()) + .filter(|e| e.data_source != DataSource::Basenames) .collect(); + if filter_edges.len() == 0 { - return Ok(None); + // only have basenames edges + let basenames_vertex: Vec = result + .vertices + .clone() + .into_iter() + .filter(|v| v.record.platform == Platform::Ethereum) + .collect(); + + if basenames_vertex.len() > 0 { + let updated_at = + basenames_vertex.first().cloned().unwrap().updated_at; + let current_time = naive_now(); + let duration_since_update = + current_time.signed_duration_since(updated_at); + // Check if the difference is greater than 2 hours + if duration_since_update > Duration::hours(2) { + tracing::info!("Basenames refetching..."); + return Ok(None); + } + } } } return Ok(Some(result)); diff --git a/src/upstream/types/contract_category.rs b/src/upstream/types/contract_category.rs index 515a364..8e73a28 100644 --- a/src/upstream/types/contract_category.rs +++ b/src/upstream/types/contract_category.rs @@ -48,6 +48,11 @@ pub enum ContractCategory { #[graphql(name = "gns")] GNS, + #[strum(serialize = "basenames")] + #[serde(rename = "basenames")] + #[graphql(name = "basenames")] + Basenames, + #[default] #[serde(rename = "unknown")] #[graphql(name = "unknown")] diff --git a/src/upstream/types/data_source.rs b/src/upstream/types/data_source.rs index e4069f2..2cc5ddb 100644 --- a/src/upstream/types/data_source.rs +++ b/src/upstream/types/data_source.rs @@ -148,6 +148,14 @@ pub enum DataSource { #[graphql(name = "sns")] SNS, + /// Basenames + /// Basenames are a core onchain building block that enable builders to establish their identity on Base by registering human-readable names for their wallet address(es). + /// https://www.base.org/names + #[strum(serialize = "basenames")] + #[serde(rename = "basenames")] + #[graphql(name = "basenames")] + Basenames, + /// opensea /// https://opensea.io /// Twitter <-> Ethereum diff --git a/src/upstream/types/domain_name.rs b/src/upstream/types/domain_name.rs index 6d4da4b..82c8c56 100644 --- a/src/upstream/types/domain_name.rs +++ b/src/upstream/types/domain_name.rs @@ -29,6 +29,14 @@ pub enum DomainNameSystem { #[graphql(name = "ens")] ENS, + /// Basenames + /// Basenames are a core onchain building block that enable builders to establish their identity on Base by registering human-readable names for their wallet address(es). + /// https://www.base.org/names + #[strum(serialize = "basenames")] + #[serde(rename = "basenames")] + #[graphql(name = "basenames")] + Basenames, + /// SNS: Solana Name Service /// https://www.sns.id #[strum(serialize = "sns")] @@ -208,6 +216,13 @@ pub enum EXT { #[graphql(name = "eth")] Eth, + /// Basenames: Basenames on L2 + /// https://www.base.org/names + #[strum(serialize = "base.eth")] + #[serde(rename = "base.eth")] + #[graphql(name = "base.eth")] + BaseEth, + /// https://www.sns.id: Solana Name Service #[strum(serialize = "sol")] #[serde(rename = "sol")] @@ -444,6 +459,7 @@ lazy_static! { pub static ref EXTENSION: HashMap> = { let mut extension = HashMap::new(); extension.insert(Platform::ENS, vec![EXT::Eth]); // name.eth + extension.insert(Platform::Basenames, vec![EXT::BaseEth]); // name.base.eth extension.insert(Platform::SNS, vec![EXT::Sol]); // name.sol extension.insert(Platform::Dotbit, vec![EXT::Bit]); // name.bit extension.insert(Platform::Lens, vec![EXT::Lens]); // lens/handle @@ -501,6 +517,7 @@ impl From for Platform { fn from(ext: EXT) -> Self { match ext { EXT::Eth => Platform::ENS, + EXT::BaseEth => Platform::Basenames, EXT::Sol => Platform::SNS, EXT::Bit => Platform::Dotbit, EXT::Lens => Platform::Lens, @@ -552,6 +569,7 @@ impl From for DomainNameSystem { fn from(ext: EXT) -> Self { match ext { EXT::Eth => DomainNameSystem::ENS, + EXT::BaseEth => DomainNameSystem::Basenames, EXT::Sol => DomainNameSystem::SNS, EXT::Bit => DomainNameSystem::DotBit, EXT::Lens => DomainNameSystem::Lens, @@ -603,6 +621,7 @@ impl From for Platform { fn from(domain: DomainNameSystem) -> Self { match domain { DomainNameSystem::ENS => Platform::ENS, + DomainNameSystem::Basenames => Platform::Basenames, DomainNameSystem::SNS => Platform::SNS, DomainNameSystem::DotBit => Platform::Dotbit, DomainNameSystem::UnstoppableDomains => Platform::UnstoppableDomains, diff --git a/src/upstream/types/platform.rs b/src/upstream/types/platform.rs index ee958b8..ad2709a 100644 --- a/src/upstream/types/platform.rs +++ b/src/upstream/types/platform.rs @@ -104,6 +104,14 @@ pub enum Platform { #[graphql(name = "ens")] ENS, + /// Basenames: + /// Basenames are a core onchain building block that enable builders to establish their identity on Base by registering human-readable names for their wallet address(es). + /// https://www.base.org/names + #[strum(serialize = "basenames")] + #[serde(rename = "basenames")] + #[graphql(name = "basenames")] + Basenames, + /// Solana Name Service: Create a human-readable identity by replacing decentralized addresses with a domain name. /// https://www.sns.id #[strum(serialize = "sns")]