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

feat: Algolia Removal #23

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,9 +810,7 @@ const schema = yup
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: yup.string(),
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: yup.string(),
NEXT_PUBLIC_UNIVERSAL_PROFILES_API_URL: yup.string(),
NEXT_PUBLIC_ALGOLIA_APP_ID: yup.string(),
NEXT_PUBLIC_ALGOLIA_API_KEY: yup.string(),
NEXT_PUBLIC_ALGOLIA_INDEX_NAME: yup.string(),
NEXT_PUBLIC_GRAPH_URL: yup.string(),
NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: yup.string(),

// Misc
Expand Down
4 changes: 1 addition & 3 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,7 @@ Settings for meta tags, OG tags and SEO
| NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED | `boolean` | Set to `true` if SolidityScan reports are supported | - | - | `true` | v1.19.0+ |
| NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS | `Array<'solidity-hardhat' \| 'solidity-foundry'>` | Pass an array of additional methods from which users can choose while verifying a smart contract. Both methods are available by default, pass `'none'` string to disable them all. | - | - | `['solidity-hardhat']` | v1.33.0+ |
| NEXT_PUBLIC_UNIVERSAL_PROFILES_API_URL | `string` | LUKSO UNIVERSAL PROFILE API URL used for getting various universal profile data | - | - | `https://api.universalprofile.com` | - |
| NEXT_PUBLIC_ALGOLIA_APP_ID | `string` | Algolia App's ID | - | - | `ABCD1234` | - |
| NEXT_PUBLIC_ALGOLIA_API_KEY | `string` | Algolia API key used for authenticating requests | - | - | `abcd1234defg5678 `| - |
| NEXT_PUBLIC_ALGOLIA_INDEX_NAME | `string` | Index name from where data should be | - | - | `prod_mainnet_data`| - |
| NEXT_PUBLIC_GRAPH_URL | `string` | URL of LUKSO Graph Indexer | - | - | `https://envio.mainnet.lukso.dev/`| - |

##### Address views list
| Id | Description |
Expand Down
11 changes: 0 additions & 11 deletions lib/api/buildUniversalProfileUrl.ts

This file was deleted.

47 changes: 47 additions & 0 deletions lib/api/graphClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { GraphResponse } from 'types/api/universalProfile';

import { getEnvValue } from 'configs/app/utils';

import { constructQuery } from './graphQueries';
import type { QueryOperation, SearchProfileQueryResponse } from './graphTypes';

const graphUrl = getEnvValue('NEXT_PUBLIC_GRAPH_URL') || '';

type FetchFunc<T> = (queryParams?: string) => Promise<GraphResponse<T> | null>

type GraphClient = {
getProfiles: FetchFunc<SearchProfileQueryResponse>;
};

const queryParamsToGraphQuery = (operationName: QueryOperation, queryParams?: string): string => {
const query = constructQuery(operationName, queryParams);

return JSON.stringify({
operationName: operationName,
query: query,
});
};

const fetchQuery = <T>(operationName: QueryOperation): FetchFunc<T> => {
return async(queryParams?: string): Promise<GraphResponse<T> | null> => {
const query = queryParamsToGraphQuery(operationName, queryParams);

try {
const resp = await fetch(graphUrl, {
method: 'POST',
headers: {},
body: query,
});
const json = await resp.json();
return json as GraphResponse<T>;
} catch (err) {
return null;
}
};
};

const createGraphClient = (): GraphClient => ({
getProfiles: fetchQuery<SearchProfileQueryResponse>('search_profiles'),
});

export const graphClient: GraphClient = createGraphClient();
25 changes: 25 additions & 0 deletions lib/api/graphQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { QueryOperation } from './graphTypes';

type QueryConstructor = (queryParams?: string) => string;

export const constructQuery = (operationType: QueryOperation, queryParams?: string) => {
const queryConstruct = queryConstructors[operationType];

return queryConstruct(queryParams);
};

export const searchProfileQuery = (queryParams?: string): string => `query search_profiles {
search_profiles(args: { search: "${ queryParams }" }) {
profileImages(order_by: { width: asc }) {
src,
width,
},
id,
name,
fullName,
}
}`;

const queryConstructors: Record<QueryOperation, QueryConstructor> = {
search_profiles: searchProfileQuery,
};
18 changes: 18 additions & 0 deletions lib/api/graphTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export type ProfileImage = {
src: string;
width: number;
}

export type SearchProfileQueryResponse = {
profileImages: Array<ProfileImage>;
id: string;
name: string;
fullName: string;
};

export type GraphQuery = {
operationName: string;
query: string;
};

export type QueryOperation = 'search_profiles';
20 changes: 13 additions & 7 deletions lib/api/useUniversalProfileApiFetch.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

import type { SearchResultAddressOrContractOrUniversalProfile } from '../../types/api/search';
import type { UniversalProfileProxyResponse } from '../../types/api/universalProfile';

import type { Params as FetchParams } from 'lib/hooks/useFetch';

import { algoliaIndex } from './buildUniversalProfileUrl';
import { graphClient } from './graphClient';
import type { SearchProfileQueryResponse } from './graphTypes';
import { isUniversalProfileEnabled } from './isUniversalProfileEnabled';
import type { ResourceName, ResourcePathParams } from './resources';

Expand All @@ -22,13 +22,19 @@ export default function useUniversalProfileApiFetch() {
return [] as Array<SearchResultAddressOrContractOrUniversalProfile>;
}
try {
const { hits } = await algoliaIndex.search(queryParams);
return hits.map<SearchResultAddressOrContractOrUniversalProfile>((hit) => {
const hitAsUp = hit as unknown as UniversalProfileProxyResponse;
const result = await graphClient.getProfiles(queryParams);
if (result == null) {
return [] as Array<SearchResultAddressOrContractOrUniversalProfile>;
}

const hits = result.data.search_profiles as Array<SearchProfileQueryResponse>;

return hits.map<SearchResultAddressOrContractOrUniversalProfile>((hit: SearchProfileQueryResponse) => {
const hitAsUp = hit as unknown as SearchProfileQueryResponse;
return {
type: 'universal_profile',
name: hitAsUp.hasProfileName ? hitAsUp.LSP3Profile.name : null,
address: hit.objectID,
name: hitAsUp.name !== '' ? hitAsUp.name : null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering that UPs may have names to be absolutely anything if those are set outside of our mobile app or extension should we trim the name to be sure it doesn't contain only whitespace characters? 🤔
Or is it already done and here we get the trimmed version?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats a good idea, but let me check and confirm

address: hit.id,
is_smart_contract_verified: false,
};
});
Expand Down
1 change: 1 addition & 0 deletions nextjs/csp/policies/universalprofile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function universalProfile(): CspDev.DirectiveDescriptor {
'api.universalprofile.cloud',
'*.algolianet.com',
'*.algolia.net',
'envio.mainnet.lukso.dev',
],
};
}
8 changes: 8 additions & 0 deletions types/api/universalProfile.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { QueryOperation } from 'lib/api/graphTypes';

export type UniversalProfileProxyResponse = {
type: string;
hasProfileName: boolean;
Expand Down Expand Up @@ -25,3 +27,9 @@ export type UniversalProfileAlgoliaResponse = {
};
};
}

export type GraphResponse<T> = {
data: {
[key in QueryOperation]: Array<T>;
};
}
Loading