Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: query proof service #11452

Merged
merged 3 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/mask/background/services/identity/persona/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,12 @@ export async function querySocialIdentity(
identity: IdentityResolved | undefined,
): Promise<SocialIdentity | undefined> {
if (!identity?.identifier) return
const bindings = await queryPersonasFromNextID(platform, identity)
const persona = await queryPersonaByProfile(identity.identifier)
if (!persona) return identity

const bindings = await queryPersonasFromNextID(platform, identity)
if (!bindings) return identity

const personaBindings =
bindings?.filter((x) => x.persona === persona?.identifier.publicKeyAsHex.toLowerCase()) ?? []
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ async function queryPersonaFromDB(identityResolved: IdentityResolved) {

async function queryPersonasFromNextID(identityResolved: IdentityResolved) {
if (!identityResolved.identifier) return
if (!activatedSiteAdaptorUI!.configuration.nextIDConfig?.platform) return
if (!activatedSiteAdaptorUI?.configuration.nextIDConfig?.platform) return
return NextIDProof.queryAllExistedBindingsByPlatform(
activatedSiteAdaptorUI!.configuration.nextIDConfig?.platform,
activatedSiteAdaptorUI.configuration.nextIDConfig.platform,
identityResolved.identifier.userId,
)
}
Expand Down Expand Up @@ -68,10 +68,15 @@ export function useSocialIdentity(identity: IdentityResolved | null | undefined)
enabled: !!identity,
queryKey: ['social-identity', identity],
queryFn: async () => {
if (!identity) return null
try {
const bindings = await queryPersonasFromNextID(identity)
if (!identity) return null

const persona = await queryPersonaFromDB(identity)
if (!persona) return identity

const bindings = await queryPersonasFromNextID(identity)
if (!bindings) return identity

const personaBindings =
bindings?.filter((x) => x.persona === persona?.identifier.publicKeyAsHex.toLowerCase()) ?? []
return {
Expand Down
5 changes: 2 additions & 3 deletions packages/plugins/Avatar/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,12 @@ export async function getNFTAvatarByUserId(
): Promise<NextIDAvatarMeta | undefined> {
const platform = getSiteType() === EnhanceableSite.Twitter ? NextIDPlatform.Twitter : undefined
if (!platform) return

const bindings = await NextIDProof.queryAllExistedBindingsByPlatform(platform, userId)

if (persona) {
const binding = bindings.filter((x) => x.persona.toLowerCase() === persona.toLowerCase())?.[0]
if (binding) {
return getAvatarFromNextIDStorage(binding.persona, platform, userId, avatarId)
}
if (binding) return getAvatarFromNextIDStorage(binding.persona, platform, userId, avatarId)
}
for (const binding of bindings.sort((a, b) => sortPersonaBindings(a, b, userId))) {
const avatar = await getAvatarFromNextIDStorage(binding.persona, platform, userId, avatarId)
Expand Down
6 changes: 3 additions & 3 deletions packages/plugins/SmartPay/src/hooks/useQueryQualifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export function useQueryQualifications(): AsyncState<{
}
}

const response = await NextIDProof.queryAllExistedBindingsByPlatform(
const bindings = await NextIDProof.queryAllExistedBindingsByPlatform(
NextIDPlatform.Twitter,
currentIdentity.identifier.userId,
)

const verifiedPersona = intersectionWith(
personas.map((x) => ({ ...x, persona: x.identifier.publicKeyAsHex.toLowerCase() })),
response,
bindings,
(a, b) => a.persona === b.persona,
)

Expand All @@ -59,7 +59,7 @@ export function useQueryQualifications(): AsyncState<{
...x,
identity: x.address,
})),
response.flatMap((x) =>
bindings.flatMap((x) =>
x.proofs.filter((y) => y.platform === NextIDPlatform.Ethereum && isValidAddress(y.identity)),
),
(a, b) => isSameAddress(a.identity, b.identity),
Expand Down
6 changes: 3 additions & 3 deletions packages/shared/src/hooks/useConnectedPersonas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ export function useConnectedPersonas(): UseQueryResult<
> {
const personasInDB = useAllPersonas()
const result = useQuery({
enabled: personasInDB.length > 0,
queryKey: ['connected-persona', personasInDB],
queryFn: async () => {
const allPersonaPublicKeys = personasInDB.map((x) => x.identifier.publicKeyAsHex)
const allPersonaIdentifiers = personasInDB.map((x) => x.identifier)

const avatars = await queryPersonaAvatar?.(allPersonaIdentifiers)
const allNextIDBindings = await NextIDProof.queryAllExistedBindingsByPlatform(
const bindings = await NextIDProof.queryAllExistedBindingsByPlatform(
NextIDPlatform.NextID,
allPersonaPublicKeys.join(','),
undefined,
)

return personasInDB.map((x) => {
return {
persona: x,
proof:
allNextIDBindings
bindings
.find((p) => p.persona.toLowerCase() === x.identifier.publicKeyAsHex.toLowerCase())
?.proofs.filter((x) => x.is_valid) ?? EMPTY_LIST,
avatar: avatars?.get(x.identifier),
Expand Down
3 changes: 1 addition & 2 deletions packages/shared/src/hooks/usePersonasFromNextID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ export function usePersonasFromNextID(
queryKey: ['next-id', 'personas', userId],
queryFn: async () => {
if (!platform || !userId) return EMPTY_LIST
const res = await NextIDProof.queryAllExistedBindingsByPlatform(platform, userId, exact)
return res ? res : EMPTY_LIST
return NextIDProof.queryAllExistedBindingsByPlatform(platform, userId, exact)
},
})

Expand Down
74 changes: 36 additions & 38 deletions packages/web3-providers/src/NextID/proof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { staleNextIDCached } from './helpers.js'
import PRESET_LENS from './preset-lens.json'
import { fetchJSON, fetchSquashedJSON } from '../helpers/fetchJSON.js'
import type { NextIDBaseAPI } from '../entry-types.js'
import { stableSquashedCached } from '../entry-helpers.js'
import { Expiration, stableSquashedCached } from '../entry-helpers.js'
import { env } from '@masknet/flags'

const BASE_URL =
Expand Down Expand Up @@ -109,7 +109,7 @@ function relationServiceDomainQuery(depth?: number) {
}`
}

function relationServiceIdentityQuery(depth?: number) {
function relationServiceIdentityQuery(depth = 5) {
return `
identity(platform: $platform, identity: $identity) {
platform
Expand All @@ -129,7 +129,7 @@ function relationServiceIdentityQuery(depth?: number) {
address
id
}
neighborWithTraversal(depth: ${depth ?? 5}) {
neighborWithTraversal(depth: ${depth}) {
... on ProofRecord {
source
from {
Expand Down Expand Up @@ -211,12 +211,11 @@ interface RestorePubkeyResponse {
public_key: string
}

type NeighborNode = {
interface NeighborNode {
source: NextIDPlatform
to: NextIDIdentity
from: NextIDIdentity
}
type NeighborList = NeighborNode[]

function getPersonaQueryURL(platform: string, identity: string) {
return urlcat(BASE_URL, '/v1/proof', {
Expand All @@ -233,11 +232,13 @@ function getExistedBindingQueryURL(platform: string, identity: string, personaPu
})
}

export class NextIDProof {
static fetchFromProofService<T>(request: Request | RequestInfo, init?: RequestInit) {
return fetchJSON<T>(request, init)
}
function fetchFromProofService<T>(request: Request | RequestInfo, init?: RequestInit) {
return fetchJSON<T>(request, init, {
squashExpiration: Expiration.TEN_SECONDS,
})
}

export class NextIDProof {
static async clearPersonaQueryCache(personaPublicKey: string) {
const url = getPersonaQueryURL(NextIDPlatform.NextID, personaPublicKey)
await staleNextIDCached(url)
Expand Down Expand Up @@ -293,9 +294,8 @@ export class NextIDProof {
}

static async queryExistedBindingByPersona(personaPublicKey: string) {
const { ids } = await this.fetchFromProofService<NextIDBindings>(
const { ids } = await fetchFromProofService<NextIDBindings>(
getPersonaQueryURL(NextIDPlatform.NextID, personaPublicKey),
undefined,
)
// Will have only one item when query by personaPublicKey
return first(ids)
Expand All @@ -304,7 +304,7 @@ export class NextIDProof {
static async queryExistedBindingByPlatform(platform: NextIDPlatform, identity: string, page = 1, exact = true) {
if (!platform && !identity) return []

const response = await this.fetchFromProofService<NextIDBindings>(
const bindings = await fetchFromProofService<NextIDBindings>(
urlcat(BASE_URL, '/v1/proof', {
platform,
identity,
Expand All @@ -314,7 +314,7 @@ export class NextIDProof {
}),
)

return sortBy(response.ids, (x) => -x.activated_at)
return sortBy(bindings.ids, (x) => -x.activated_at)
}

static async queryLatestBindingByPlatform(
Expand All @@ -324,9 +324,9 @@ export class NextIDProof {
): Promise<NextIDPersonaBindings | null> {
if (!platform && !identity) return null

const result = await this.queryAllExistedBindingsByPlatform(platform, identity, true)
if (publicKey) return result.find((x) => x.persona === publicKey) ?? null
return first(result) ?? null
const bindings = await this.queryAllExistedBindingsByPlatform(platform, identity, true)
if (publicKey) return bindings.find((x) => x.persona === publicKey) ?? null
return first(bindings) ?? null
}

static async queryAllExistedBindingsByPlatform(platform: NextIDPlatform, identity: string, exact?: boolean) {
Expand All @@ -335,22 +335,21 @@ export class NextIDProof {
const nextIDPersonaBindings: NextIDPersonaBindings[] = []
let page = 1
do {
const result = await this.fetchFromProofService<NextIDBindings>(
const bindings = await fetchFromProofService<NextIDBindings>(
urlcat(BASE_URL, '/v1/proof', {
platform,
identity,
exact,
page,
order: 'desc',
}),
undefined,
)
const personaBindings = result.ids
const personaBindings = bindings.ids
if (personaBindings.length === 0) return nextIDPersonaBindings
nextIDPersonaBindings.push(...personaBindings)

// next is `0` if current page is the last one.
if (result.pagination.next === 0) return nextIDPersonaBindings
if (bindings.pagination.next === 0) return nextIDPersonaBindings

page += 1
} while (page > 1)
Expand All @@ -361,11 +360,10 @@ export class NextIDProof {
try {
if (!platform && !identity) return false

const result = await this.fetchFromProofService<BindingProof | undefined>(
const proof = await fetchFromProofService<BindingProof | undefined>(
getExistedBindingQueryURL(platform, identity, personaPublicKey),
undefined,
)
return !!result?.is_valid
return !!proof?.is_valid
} catch {
return false
}
Expand All @@ -378,7 +376,7 @@ export class NextIDProof {
data: {
domain: {
owner: {
neighborWithTraversal: NeighborList
neighborWithTraversal: NeighborNode[]
nft: NextIDEnsRecord[]
}
} | null
Expand All @@ -396,8 +394,8 @@ export class NextIDProof {
`,
}),
})

if (!data.domain) return EMPTY_LIST

const bindings = createBindProofsFromNeighbor(data.domain.owner.neighborWithTraversal)
return bindings.filter((x) => ![NextIDPlatform.NextID].includes(x.platform) && x.identity)
}
Expand All @@ -407,7 +405,7 @@ export class NextIDProof {
data: {
identity: {
nft: NextIDEnsRecord[]
neighborWithTraversal: NeighborList
neighborWithTraversal: NeighborNode[]
}
}
}>(RELATION_SERVICE_URL, {
Expand All @@ -419,7 +417,7 @@ export class NextIDProof {
query: `
query GET_PROFILES_QUERY($platform: String, $identity: String) {
${relationServiceIdentityQuery(depth)}
}
}
`,
}),
})
Expand All @@ -435,7 +433,7 @@ export class NextIDProof {
data: {
identity: {
nft: NextIDEnsRecord[]
neighborWithTraversal: NeighborList
neighborWithTraversal: NeighborNode[]
}
}
}>(RELATION_SERVICE_URL, {
Expand All @@ -447,7 +445,7 @@ export class NextIDProof {
query: `
query GET_PROFILES_QUERY($platform: String, $identity: String) {
${relationServiceIdentityQuery(depth)}
}
}
`,
}),
})
Expand All @@ -460,7 +458,7 @@ export class NextIDProof {
data: {
identity: {
nft: NextIDEnsRecord[]
neighborWithTraversal: NeighborList
neighborWithTraversal: NeighborNode[]
}
}
}>(RELATION_SERVICE_URL, {
Expand All @@ -470,9 +468,9 @@ export class NextIDProof {
operationName: 'GET_PROFILES_BY_TWITTER_ID',
variables: { platform: NextIDPlatform.Twitter, identity: twitterId.toLowerCase() },
query: `
query GET_PROFILES_BY_TWITTER_ID($platform: String, $identity: String) {
${relationServiceIdentityQuery(depth)}
}
query GET_PROFILES_BY_TWITTER_ID($platform: String, $identity: String) {
${relationServiceIdentityQuery(depth)}
}
`,
}),
})
Expand All @@ -486,7 +484,7 @@ export class NextIDProof {
data: {
domain: {
owner: {
neighborWithTraversal: NeighborList
neighborWithTraversal: NeighborNode[]
}
} | null
}
Expand All @@ -497,9 +495,9 @@ export class NextIDProof {
operationName: 'GET_LENS_PROFILES',
variables: { domainSystem: 'lens', domain: lowerCaseId },
query: `
query GET_LENS_PROFILES($domainSystem: String, $domain: String) {
${relationServiceDomainQuery(depth)}
}
query GET_LENS_PROFILES($domainSystem: String, $domain: String) {
${relationServiceDomainQuery(depth)}
}
`,
}),
})
Expand Down Expand Up @@ -593,7 +591,7 @@ function createBindingProofNodeFromNeighbor(nextIDIdentity: NextIDIdentity, sour
)
}

function createBindProofsFromNeighbor(neighborList: NeighborList): BindingProof[] {
function createBindProofsFromNeighbor(neighborList: NeighborNode[]): BindingProof[] {
const bindings = neighborList.flatMap((x) => {
return [
{
Expand Down
1 change: 1 addition & 0 deletions packages/web3-providers/src/helpers/fetchSquashed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { fetch: originalFetch } = globalThis

export enum Expiration {
ONE_SECOND = 1000,
TEN_SECONDS = 10000,
ONE_MINUTE = 60000,
THIRTY_MINUTES = 1800000,
ONE_HOUR = 3600000,
Expand Down