Commit cd27e8fc authored by tom goriunov's avatar tom goriunov Committed by GitHub

Zilliqa: filter for Scilla contracts (#2449)

* Zilliqa: filter for Scilla contracts

Fixes #2427

* [skip ci] review fixes
parent 196a4b8b
import type { VerifiedContractsFilter } from 'types/api/contracts';
import type { SmartContractVerificationMethodExtra } from 'types/client/contract'; 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 type { AddressFormat, AddressViewId, IdenticonType } from 'types/views/address';
import { ADDRESS_FORMATS, ADDRESS_VIEWS_IDS, IDENTICON_TYPES } from 'types/views/address'; import { ADDRESS_FORMATS, ADDRESS_VIEWS_IDS, IDENTICON_TYPES } from 'types/views/address';
...@@ -58,9 +59,20 @@ const extraVerificationMethods: Array<SmartContractVerificationMethodExtra> = (( ...@@ -58,9 +59,20 @@ const extraVerificationMethods: Array<SmartContractVerificationMethodExtra> = ((
return SMART_CONTRACT_EXTRA_VERIFICATION_METHODS; return SMART_CONTRACT_EXTRA_VERIFICATION_METHODS;
} }
const parsedMethods = parseEnvJson<Array<SmartContractVerificationMethodExtra>>(getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS')) || []; const parsedMethods = parseEnvJson<Array<SmartContractVerificationMethodExtra>>(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<VerifiedContractsFilter> = (() => {
const envValue = parseEnvJson<Array<VerifiedContractsFilter>>(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({ const config = Object.freeze({
...@@ -72,6 +84,7 @@ const config = Object.freeze({ ...@@ -72,6 +84,7 @@ const config = Object.freeze({
hiddenViews, hiddenViews,
solidityscanEnabled: getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED') === 'true', solidityscanEnabled: getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED') === 'true',
extraVerificationMethods, extraVerificationMethods,
languageFilters,
}); });
export default config; export default config;
...@@ -9,9 +9,8 @@ NEXT_PUBLIC_APP_PORT=3000 ...@@ -9,9 +9,8 @@ NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['bech32','base16'] NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil
NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['base_fee']
# Instance ENVs # Instance ENVs
NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_BASE_PATH=/
...@@ -20,7 +19,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout ...@@ -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_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_GRAPHIQL_TRANSACTION=0x3d1ded3a7924cd3256a4b1a447c9bfb194f54b9a8ceb441edb8bb01563b516db
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] 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_IS_TESTNET=true
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18 NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
...@@ -36,6 +35,7 @@ NEXT_PUBLIC_NETWORK_RPC_URL=https://api.zq2-prototestnet.zilliqa.com ...@@ -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_NETWORK_SHORT_NAME=Zilliqa EVM proto-testnet
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true 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_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_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 NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
...@@ -13,7 +13,7 @@ import type { AdButlerConfig } from '../../../types/client/adButlerConfig'; ...@@ -13,7 +13,7 @@ import type { AdButlerConfig } from '../../../types/client/adButlerConfig';
import type { AddressProfileAPIConfig } from '../../../types/client/addressProfileAPIConfig'; 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 { 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 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 { DeFiDropdownItem } from '../../../types/client/deFiDropdown';
import type { GasRefuelProviderConfig } from '../../../types/client/gasRefuelProviderConfig'; import type { GasRefuelProviderConfig } from '../../../types/client/gasRefuelProviderConfig';
import { GAS_UNITS } from '../../../types/client/gasTracker'; import { GAS_UNITS } from '../../../types/client/gasTracker';
...@@ -42,6 +42,7 @@ import type { BlockFieldId } from '../../../types/views/block'; ...@@ -42,6 +42,7 @@ import type { BlockFieldId } from '../../../types/views/block';
import type { NftMarketplaceItem } from '../../../types/views/nft'; import type { NftMarketplaceItem } from '../../../types/views/nft';
import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx'; import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx';
import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS } 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 { replaceQuotes } from '../../../configs/app/utils';
import * as regexp from '../../../lib/regexp'; import * as regexp from '../../../lib/regexp';
...@@ -719,6 +720,12 @@ const schema = yup ...@@ -719,6 +720,12 @@ const schema = yup
return isNoneSchema.isValidSync(data) || isArrayOfMethodsSchema.isValidSync(data); return isNoneSchema.isValidSync(data) || isArrayOfMethodsSchema.isValidSync(data);
}), }),
NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS: yup
.array()
.transform(replaceQuotes)
.json()
.of(yup.string<VerifiedContractsFilter>().oneOf(SMART_CONTRACT_LANGUAGE_FILTERS)),
NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: yup NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: yup
.array() .array()
.transform(replaceQuotes) .transform(replaceQuotes)
......
...@@ -74,6 +74,7 @@ NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar ...@@ -74,6 +74,7 @@ NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16'] NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16']
NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts'] NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts']
NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=['solidity-hardhat','solidity-foundry'] 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_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_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'] NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas']
......
...@@ -243,6 +243,7 @@ Settings for meta tags, OG tags and SEO ...@@ -243,6 +243,7 @@ Settings for meta tags, OG tags and SEO
| NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS | `Array<AddressViewId>` | Address views that should not be displayed. See below the list of the possible id values. | - | - | `'["top_accounts"]'` | v1.15.0+ | | NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS | `Array<AddressViewId>` | 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_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_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 ##### Address views list
| Id | Description | | Id | Description |
......
...@@ -24,9 +24,11 @@ export interface VerifiedContractsResponse { ...@@ -24,9 +24,11 @@ export interface VerifiedContractsResponse {
} | null; } | null;
} }
export type VerifiedContractsFilter = 'solidity' | 'vyper' | 'yul' | 'scilla';
export interface VerifiedContractsFilters { export interface VerifiedContractsFilters {
q: string | undefined; q: string | undefined;
filter: 'vyper' | 'solidity' | 'yul' | undefined; filter: VerifiedContractsFilter | undefined;
} }
export type VerifiedContractsCounters = { export type VerifiedContractsCounters = {
......
import type { SmartContractLicenseType, SmartContractVerificationConfigRaw, SmartContractVerificationMethodApi } from 'types/api/contract'; import type { SmartContractLicenseType, SmartContractVerificationConfigRaw, SmartContractVerificationMethodApi } from 'types/api/contract';
import type { VerifiedContractsFilter } from 'types/api/contracts';
export interface ContractCodeIde { export interface ContractCodeIde {
title: string; title: string;
...@@ -25,3 +26,10 @@ export type SmartContractVerificationMethod = SmartContractVerificationMethodApi ...@@ -25,3 +26,10 @@ export type SmartContractVerificationMethod = SmartContractVerificationMethodApi
export interface SmartContractVerificationConfig extends SmartContractVerificationConfigRaw { export interface SmartContractVerificationConfig extends SmartContractVerificationConfigRaw {
verification_options: Array<SmartContractVerificationMethod>; verification_options: Array<SmartContractVerificationMethod>;
} }
export const SMART_CONTRACT_LANGUAGE_FILTERS: Array<VerifiedContractsFilter> = [
'solidity',
'vyper',
'yul',
'scilla',
];
import React from 'react'; 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'; import PopoverFilterRadio from 'ui/shared/filters/PopoverFilterRadio';
type OptionValue = TVerifiedContractsFilter | 'all';
const OPTIONS = [ const OPTIONS = [
{ value: 'all', label: 'All' }, { value: 'all', label: 'All' },
{ value: 'solidity', label: 'Solidity' }, { value: 'solidity', label: 'Solidity' },
{ value: 'vyper', label: 'Vyper' }, { value: 'vyper', label: 'Vyper' },
{ value: 'yul', label: 'Yul' }, { 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 { interface Props {
hasActiveFilter: boolean; hasActiveFilter: boolean;
defaultValue: VerifiedContractsFilters['filter'] | undefined; defaultValue: TVerifiedContractsFilter | undefined;
onChange: (nextValue: string | Array<string>) => void; onChange: (nextValue: string | Array<string>) => void;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment