diff --git a/configs/app/ui/views/address.ts b/configs/app/ui/views/address.ts index 6794a2735f..8972c02fce 100644 --- a/configs/app/ui/views/address.ts +++ b/configs/app/ui/views/address.ts @@ -1,5 +1,6 @@ +import type { VerifiedContractsFilter } from 'types/api/contracts'; import type { SmartContractVerificationMethodExtra } from 'types/client/contract'; -import { SMART_CONTRACT_EXTRA_VERIFICATION_METHODS } from 'types/client/contract'; +import { SMART_CONTRACT_EXTRA_VERIFICATION_METHODS, SMART_CONTRACT_LANGUAGE_FILTERS } from 'types/client/contract'; import type { AddressFormat, AddressViewId, IdenticonType } from 'types/views/address'; import { ADDRESS_FORMATS, ADDRESS_VIEWS_IDS, IDENTICON_TYPES } from 'types/views/address'; @@ -58,9 +59,20 @@ const extraVerificationMethods: Array = (( return SMART_CONTRACT_EXTRA_VERIFICATION_METHODS; } - const parsedMethods = parseEnvJson>(getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS')) || []; + const parsedMethods = parseEnvJson>(envValue) || []; - return SMART_CONTRACT_EXTRA_VERIFICATION_METHODS.filter((method) => parsedMethods.includes(method)); + return parsedMethods.filter((method) => SMART_CONTRACT_EXTRA_VERIFICATION_METHODS.includes(method)); +})(); + +const languageFilters: Array = (() => { + const envValue = parseEnvJson>(getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS')); + if (!envValue) { + // "Scilla" is chain specific language, so we don't want to show it in default scenario + const DEFAULT_LANGUAGE_FILTERS = SMART_CONTRACT_LANGUAGE_FILTERS.filter((filter) => filter !== 'scilla'); + return DEFAULT_LANGUAGE_FILTERS; + } + + return envValue.filter((filter) => SMART_CONTRACT_LANGUAGE_FILTERS.includes(filter)); })(); const config = Object.freeze({ @@ -72,6 +84,7 @@ const config = Object.freeze({ hiddenViews, solidityscanEnabled: getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED') === 'true', extraVerificationMethods, + languageFilters, }); export default config; diff --git a/configs/envs/.env.zilliqa_prototestnet b/configs/envs/.env.zilliqa_prototestnet index cc40958ae8..00730e8999 100644 --- a/configs/envs/.env.zilliqa_prototestnet +++ b/configs/envs/.env.zilliqa_prototestnet @@ -9,9 +9,8 @@ NEXT_PUBLIC_APP_PORT=3000 NEXT_PUBLIC_APP_ENV=development NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws -NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['bech32','base16'] -NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil -NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['base_fee'] +NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla'] + # Instance ENVs NEXT_PUBLIC_API_BASE_PATH=/ @@ -20,7 +19,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}] NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x3d1ded3a7924cd3256a4b1a447c9bfb194f54b9a8ceb441edb8bb01563b516db NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] -NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgba(52,103, 109, 1) 0.06%, rgba(105, 181, 172, 1) 99.97%)'],'text_color':['rgba(255, 255, 255, 1)']} +NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgba(0, 208, 198, 1) 0.06%, rgba(43, 146, 151, 1) 99.97%)','linear-gradient(90deg, rgba(0, 208, 198, 1) 0.06%, rgba(43, 146, 151, 1) 50.02%, rgba(0, 0, 0, 1) 99.97%)'],'text_color':['rgba(255, 255, 255, 1)','rgba(255, 255, 255, 1)'],'button':{'_default':{'background':['rgba(38, 6, 124, 1)']},'_hover':{'background':['rgba(17, 4, 87, 1)']}}} NEXT_PUBLIC_IS_TESTNET=true NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18 @@ -36,6 +35,7 @@ NEXT_PUBLIC_NETWORK_RPC_URL=https://api.zq2-prototestnet.zilliqa.com NEXT_PUBLIC_NETWORK_SHORT_NAME=Zilliqa EVM proto-testnet NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/zilliqa.png -NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=6Ld0iT8aAAAAAJdju0CmAwGjW7JTDvIw-Q5pwt5T NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout +NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil +NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=["base16", "bech32"] NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com \ No newline at end of file diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index c5752cc308..355c67484e 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -13,7 +13,7 @@ import type { AdButlerConfig } from '../../../types/client/adButlerConfig'; import type { AddressProfileAPIConfig } from '../../../types/client/addressProfileAPIConfig'; import { SUPPORTED_AD_TEXT_PROVIDERS, SUPPORTED_AD_BANNER_PROVIDERS, SUPPORTED_AD_BANNER_ADDITIONAL_PROVIDERS } from '../../../types/client/adProviders'; import type { AdTextProviders, AdBannerProviders, AdBannerAdditionalProviders } from '../../../types/client/adProviders'; -import { SMART_CONTRACT_EXTRA_VERIFICATION_METHODS, type ContractCodeIde, type SmartContractVerificationMethodExtra } from '../../../types/client/contract'; +import { SMART_CONTRACT_EXTRA_VERIFICATION_METHODS, SMART_CONTRACT_LANGUAGE_FILTERS, type ContractCodeIde, type SmartContractVerificationMethodExtra } from '../../../types/client/contract'; import type { DeFiDropdownItem } from '../../../types/client/deFiDropdown'; import type { GasRefuelProviderConfig } from '../../../types/client/gasRefuelProviderConfig'; import { GAS_UNITS } from '../../../types/client/gasTracker'; @@ -42,6 +42,7 @@ import type { BlockFieldId } from '../../../types/views/block'; import type { NftMarketplaceItem } from '../../../types/views/nft'; import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx'; import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS } from '../../../types/views/tx'; +import type { VerifiedContractsFilter } from '../../../types/api/contracts'; import { replaceQuotes } from '../../../configs/app/utils'; import * as regexp from '../../../lib/regexp'; @@ -719,6 +720,12 @@ const schema = yup return isNoneSchema.isValidSync(data) || isArrayOfMethodsSchema.isValidSync(data); }), + NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS: yup + .array() + .transform(replaceQuotes) + .json() + .of(yup.string().oneOf(SMART_CONTRACT_LANGUAGE_FILTERS)), + NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: yup .array() .transform(replaceQuotes) diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index 1024b67be1..6f47b0afce 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -74,6 +74,7 @@ NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16'] NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts'] NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=['solidity-hardhat','solidity-foundry'] +NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla'] NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward'] NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'NFT Marketplace','collection_url':'https://example.com/{hash}','instance_url':'https://example.com/{hash}/{id}','logo_url':'https://example.com/logo.png'}] NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas'] diff --git a/docs/ENVS.md b/docs/ENVS.md index c33294261f..016ef289bc 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -243,6 +243,7 @@ Settings for meta tags, OG tags and SEO | NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS | `Array` | Address views that should not be displayed. See below the list of the possible id values. | - | - | `'["top_accounts"]'` | v1.15.0+ | | 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_VIEWS_CONTRACT_LANGUAGE_FILTERS | `Array<'solidity' \| 'vyper' \| 'yul' \| 'scilla'>` | Pass an array of contract languages that will be displayed as options in the filter on the verified contract page. | - | `['solidity','vyper','yul']` | `['solidity','vyper','yul','scilla']` | v1.37.0+ | ##### Address views list | Id | Description | diff --git a/types/api/contracts.ts b/types/api/contracts.ts index d24edd49bd..1c6af55ee0 100644 --- a/types/api/contracts.ts +++ b/types/api/contracts.ts @@ -24,9 +24,11 @@ export interface VerifiedContractsResponse { } | null; } +export type VerifiedContractsFilter = 'solidity' | 'vyper' | 'yul' | 'scilla'; + export interface VerifiedContractsFilters { q: string | undefined; - filter: 'vyper' | 'solidity' | 'yul' | undefined; + filter: VerifiedContractsFilter | undefined; } export type VerifiedContractsCounters = { diff --git a/types/client/contract.ts b/types/client/contract.ts index 66fca3531c..95aed6816a 100644 --- a/types/client/contract.ts +++ b/types/client/contract.ts @@ -1,4 +1,5 @@ import type { SmartContractLicenseType, SmartContractVerificationConfigRaw, SmartContractVerificationMethodApi } from 'types/api/contract'; +import type { VerifiedContractsFilter } from 'types/api/contracts'; export interface ContractCodeIde { title: string; @@ -25,3 +26,10 @@ export type SmartContractVerificationMethod = SmartContractVerificationMethodApi export interface SmartContractVerificationConfig extends SmartContractVerificationConfigRaw { verification_options: Array; } + +export const SMART_CONTRACT_LANGUAGE_FILTERS: Array = [ + 'solidity', + 'vyper', + 'yul', + 'scilla', +]; diff --git a/ui/verifiedContracts/VerifiedContractsFilter.tsx b/ui/verifiedContracts/VerifiedContractsFilter.tsx index 7b8d9e6698..9b8afd5f63 100644 --- a/ui/verifiedContracts/VerifiedContractsFilter.tsx +++ b/ui/verifiedContracts/VerifiedContractsFilter.tsx @@ -1,19 +1,23 @@ import React from 'react'; -import type { VerifiedContractsFilters } from 'types/api/contracts'; +import type { VerifiedContractsFilter as TVerifiedContractsFilter } from 'types/api/contracts'; +import config from 'configs/app'; import PopoverFilterRadio from 'ui/shared/filters/PopoverFilterRadio'; +type OptionValue = TVerifiedContractsFilter | 'all'; + const OPTIONS = [ { value: 'all', label: 'All' }, { value: 'solidity', label: 'Solidity' }, { value: 'vyper', label: 'Vyper' }, { value: 'yul', label: 'Yul' }, -]; + { value: 'scilla', label: 'Scilla' }, +].filter(({ value }) => value === 'all' || config.UI.views.address.languageFilters.includes(value)) as Array<{ value: OptionValue; label: string }>; interface Props { hasActiveFilter: boolean; - defaultValue: VerifiedContractsFilters['filter'] | undefined; + defaultValue: TVerifiedContractsFilter | undefined; onChange: (nextValue: string | Array) => void; }