Skip to content

Commit

Permalink
Humanity score integration (#2354)
Browse files Browse the repository at this point in the history
* Humanity score integration

* isLoading fix
  • Loading branch information
isstuev authored Nov 4, 2024
1 parent c91bd81 commit e0b89d0
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 2 deletions.
1 change: 1 addition & 0 deletions configs/app/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export { default as addressProfileAPI } from './addressProfileAPI';
export { default as validators } from './validators';
export { default as verifiedTokens } from './verifiedTokens';
export { default as web3Wallet } from './web3Wallet';
export { default as xStarScore } from './xStarScore';
23 changes: 23 additions & 0 deletions configs/app/features/xStarScore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Feature } from './types';

import { getEnvValue } from '../utils';

const title = 'Xname score';
const url = getEnvValue('NEXT_PUBLIC_XNAME_SCORE_URL');

const config: Feature<{ url: string }> = (() => {
if (url) {
return Object.freeze({
title,
url,
isEnabled: true,
});
}

return Object.freeze({
title,
isEnabled: false,
});
})();

export default config;
1 change: 1 addition & 0 deletions configs/envs/.env.eth_sepolia
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=noves
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://points.k8s-dev.blockscout.com
NEXT_PUBLIC_XSTAR_SCORE_URL='https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address'
1 change: 1 addition & 0 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ const schema = yup
return isUndefined || valueSchema.isValidSync(data);
}),
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST: yup.string().test(urlTest),
NEXT_PUBLIC_XSTAR_SCORE_URL: yup.string().test(urlTest),

// 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
Expand Down
11 changes: 11 additions & 0 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
- [Bridged tokens](ENVS.md#bridged-tokens)
- [Safe{Core} address tags](ENVS.md#safecore-address-tags)
- [Address profile API](ENVS.md#address-profile-api)
- [Address XStar XHS score](ENVS.md#address-xstar-xhs-score)
- [SUAVE chain](ENVS.md#suave-chain)
- [MetaSuites extension](ENVS.md#metasuites-extension)
- [Validators list](ENVS.md#validators-list)
Expand Down Expand Up @@ -680,6 +681,16 @@ This feature allows the integration of an external API to fetch user info for ad

&nbsp;

### Address XStar XHS score

This feature allows the integration of an XStar API to fetch XHS score for addresses. When configured, if the API returns a score, a public tag with that score will be displayed in the address page header.

| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_XSTAR_SCORE_URL | `string` | XStar XHS score documentation URL for the address tag. Enables the XStar score feature. | - | - | `https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm` | v1.36.0+ |

&nbsp;

### SUAVE chain

For blockchains that implement SUAVE architecture additional fields will be shown on the transaction page ("Allowed peekers", "Kettle"). Users also will be able to see the list of all transactions for a particular Kettle in the separate view.
Expand Down
6 changes: 6 additions & 0 deletions lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import type {
AddressMudRecordsSorting,
AddressMudRecord,
AddressEpochRewardsResponse,
AddressXStarResponse,
} from 'types/api/address';
import type { AddressesResponse, AddressesMetadataSearchResult, AddressesMetadataSearchFilters } from 'types/api/addresses';
import type { AddressMetadataInfo, PublicTagTypesResponse } from 'types/api/addressMetadata';
Expand Down Expand Up @@ -595,6 +596,10 @@ export const RESOURCES = {
pathParams: [ 'hash' as const ],
filterFields: [],
},
address_xstar_score: {
path: '/api/v2/proxy/xname/address/:hash',
pathParams: [ 'hash' as const ],
},

// CONTRACT
contract: {
Expand Down Expand Up @@ -1304,6 +1309,7 @@ Q extends 'rewards_user_daily_check' ? RewardsUserDailyCheckResponse :
Q extends 'rewards_user_daily_claim' ? RewardsUserDailyClaimResponse :
Q extends 'rewards_user_referrals' ? RewardsUserReferralsResponse :
Q extends 'token_transfers_all' ? TokenTransferResponse :
Q extends 'address_xstar_score' ? AddressXStarResponse :
never;
/* eslint-enable @typescript-eslint/indent */

Expand Down
51 changes: 51 additions & 0 deletions lib/xStarScore/useFetchXStarScore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import * as v from 'valibot';

import config from 'configs/app';
import buildUrl from 'lib/api/buildUrl';
import useApiQuery from 'lib/api/useApiQuery';

interface Params {
hash: string;
}

const RESOURCE_NAME = 'address_xstar_score';
const ERROR_NAME = 'Invalid response schema';

export default function useFetchXStarScore({ hash }: Params) {
const query = useApiQuery(RESOURCE_NAME, {
pathParams: { hash },
queryOptions: {
select: (response) => {
const parsedResponse = v.safeParse(v.object({ data: v.string() }), response);

if (!parsedResponse.success) {
throw Error(ERROR_NAME);
}

return parsedResponse.output;
},
enabled: Boolean(hash) && config.features.xStarScore.isEnabled,
placeholderData: {
data: 'Base' as const,
},
retry: 0,
},
});

const errorMessage = query.error && 'message' in query.error ? query.error.message : undefined;

React.useEffect(() => {
if (errorMessage === ERROR_NAME) {
fetch('/node-api/monitoring/invalid-api-schema', {
method: 'POST',
body: JSON.stringify({
resource: RESOURCE_NAME,
url: buildUrl(RESOURCE_NAME, { hash }, undefined, true),
}),
});
}
}, [ errorMessage, hash ]);

return query;
}
4 changes: 4 additions & 0 deletions types/api/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,7 @@ export type AddressEpochRewardsItem = {
epoch_number: number;
associated_account: AddressParam;
}

export type AddressXStarResponse = {
data: string | null;
}
33 changes: 31 additions & 2 deletions ui/pages/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import getNetworkValidationActionText from 'lib/networks/getNetworkValidationAct
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import useFetchXStarScore from 'lib/xStarScore/useFetchXStarScore';
import { ADDRESS_TABS_COUNTERS } from 'stubs/address';
import { USER_OPS_ACCOUNT } from 'stubs/userOps';
import AddressAccountHistory from 'ui/address/AddressAccountHistory';
Expand Down Expand Up @@ -58,6 +59,7 @@ const TOKEN_TABS = [ 'tokens_erc20', 'tokens_nfts', 'tokens_nfts_collection', 't

const txInterpretation = config.features.txInterpretation;
const addressProfileAPIFeature = config.features.addressProfileAPI;
const xScoreFeature = config.features.xStarScore;

const AddressPageContent = () => {
const router = useRouter();
Expand Down Expand Up @@ -139,6 +141,8 @@ const AddressPageContent = () => {
const isSafeAddress = useIsSafeAddress(!addressQuery.isPlaceholderData && addressQuery.data?.is_contract ? hash : undefined);
const safeIconColor = useColorModeValue('black', 'white');

const xStarQuery = useFetchXStarScore({ hash });

const contractTabs = useContractTabs(
addressQuery.data,
config.features.mudFramework.isEnabled ? (mudTablesCountQuery.isPlaceholderData || addressQuery.isPlaceholderData) : addressQuery.isPlaceholderData,
Expand Down Expand Up @@ -295,8 +299,32 @@ const AddressPageContent = () => {
undefined,
...formatUserTags(addressQuery.data),
...(addressMetadataQuery.data?.addresses?.[hash.toLowerCase()]?.tags.filter(tag => tag.tagType !== 'note') || []),
!addressQuery.data?.is_contract && xScoreFeature.isEnabled && xStarQuery.data?.data ?
{
slug: 'xstar',
name: `XHS ${ xStarQuery.data.data } level`,
tagType: 'custom' as const,
ordinal: 12,
meta: {
tagUrl: xScoreFeature.url,
tooltipTitle: 'XStar humanity levels',
tooltipDescription:
'XStar looks for off-chain information about an address and interpret it as a XHS score. Different score means different humanity levels.',
tooltipUrl: xScoreFeature.url,
},
} :
undefined,
].filter(Boolean).sort(sortEntityTags);
}, [ addressMetadataQuery.data, addressQuery.data, hash, isSafeAddress, userOpsAccountQuery.data, mudTablesCountQuery.data, usernameApiTag ]);
}, [
addressMetadataQuery.data,
addressQuery.data,
hash,
isSafeAddress,
userOpsAccountQuery.data,
mudTablesCountQuery.data,
usernameApiTag,
xStarQuery.data?.data,
]);

const titleContentAfter = (
<EntityTags
Expand All @@ -305,7 +333,8 @@ const AddressPageContent = () => {
isLoading ||
(config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData) ||
(config.features.addressMetadata.isEnabled && addressMetadataQuery.isPending) ||
(addressProfileAPIFeature.isEnabled && userPropfileApiQuery.isPending)
(addressProfileAPIFeature.isEnabled && userPropfileApiQuery.isPending) ||
(xScoreFeature.isEnabled && xStarQuery.isPlaceholderData)
}
/>
);
Expand Down

0 comments on commit e0b89d0

Please sign in to comment.