Commit 8facbe5e authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #2248 from blockscout/fe-2195

filecoin addresses support
parents ae26fd9f ef7e9938
...@@ -19,6 +19,7 @@ on: ...@@ -19,6 +19,7 @@ on:
- eth - eth
- eth_sepolia - eth_sepolia
- eth_goerli - eth_goerli
- filecoin
- optimism - optimism
- optimism_celestia - optimism_celestia
- optimism_sepolia - optimism_sepolia
......
...@@ -19,6 +19,7 @@ on: ...@@ -19,6 +19,7 @@ on:
- eth - eth
- eth_sepolia - eth_sepolia
- eth_goerli - eth_goerli
- filecoin
- optimism - optimism
- optimism_celestia - optimism_celestia
- optimism_sepolia - optimism_sepolia
......
...@@ -367,6 +367,7 @@ ...@@ -367,6 +367,7 @@
"eth", "eth",
"eth_goerli", "eth_goerli",
"eth_sepolia", "eth_sepolia",
"filecoin",
"optimism", "optimism",
"optimism_celestia", "optimism_celestia",
"optimism_sepolia", "optimism_sepolia",
......
# Set of ENVs for Arbitrum One network explorer # Set of ENVs for Arbitrum One network explorer
# https://arbitrum.blockscout.com # https://arbitrum.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=arbitrum" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=arbitrum"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Arbitrum One network explorer # Set of ENVs for Arbitrum One network explorer
# https://arbitrum.blockscout.com # https://arbitrum.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=arbitrum" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=arbitrum"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Base Mainnet network explorer # Set of ENVs for Base Mainnet network explorer
# https://base.blockscout.com # https://base.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=base" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=base"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Celo Alfajores network explorer # Set of ENVs for Celo Alfajores network explorer
# https://celo-alfajores.blockscout.com # https://celo-alfajores.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=celo_alfajores" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=celo_alfajores"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Ethereum network explorer # Set of ENVs for Ethereum network explorer
# https://eth.blockscout.com # https://eth.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=eth" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=eth"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Sepolia network explorer # Set of ENVs for Sepolia network explorer
# https://eth-sepolia.blockscout.com # https://eth-sepolia.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=eth_sepolia" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=eth_sepolia"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Filecoin Virtual Machine network explorer
# https://filecoin.blockscout.com
# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=filecoin"
# Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
# Instance ENVs
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=filecoin.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
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_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/fvm.json
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x5abb6212c1802402b828ed20c2bd4d4a6153b8bee68a5259cba3c8d7a7c6b775
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=linear-gradient(237deg, rgb(26, 58, 150) 14.83%, rgb(111, 223, 164) 132.56%)
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=rgba(255, 255, 255, 1)
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-filecoin.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_ENABLED=false
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=FIL
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=FIL
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/filecoin/pools'}}]
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/filecoin-icon-dark.svg
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/filecoin-icon-light.svg
NEXT_PUBLIC_NETWORK_ID=314
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/filecoin-logo-dark.svg
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/filecoin-logo-light.svg
NEXT_PUBLIC_NETWORK_NAME=Filecoin Virtual Machine
NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.ankr.com/filecoin
NEXT_PUBLIC_NETWORK_SHORT_NAME=Filecoin Virtual Machine
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/filecoin.png
NEXT_PUBLIC_STATS_API_HOST=https://stats-filecoin.k8s-prod-1.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
# Set of ENVs for Gnosis chain network explorer # Set of ENVs for Gnosis chain network explorer
# https://gnosis.blockscout.com # https://gnosis.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=gnosis" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=gnosis"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Sepolia network explorer # Set of ENVs for Sepolia network explorer
# https://eth-sepolia.k8s-dev.blockscout.com # https://eth-sepolia.k8s-dev.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=main" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=main"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for OP Mainnet network explorer # Set of ENVs for OP Mainnet network explorer
# https://optimism.blockscout.com # https://optimism.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=optimism" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for OP Celestia Raspberry network explorer # Set of ENVs for OP Celestia Raspberry network explorer
# https://opcelestia-raspberry.gelatoscout.com # https://opcelestia-raspberry.gelatoscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=optimism_celestia" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism_celestia"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for OP Sepolia network explorer # Set of ENVs for OP Sepolia network explorer
# https://optimism-sepolia.blockscout.com # https://optimism-sepolia.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=optimism_sepolia" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism_sepolia"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Polygon Mainnet network explorer # Set of ENVs for Polygon Mainnet network explorer
# https://polygon.blockscout.com # https://polygon.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=polygon" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=polygon"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Rootstock Testnet network explorer # Set of ENVs for Rootstock Testnet network explorer
# https://rootstock-testnet.blockscout.com # https://rootstock-testnet.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=rootstock_testnet" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=rootstock_testnet"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Stability Testnet network explorer # Set of ENVs for Stability Testnet network explorer
# https://stability-testnet.blockscout.com # https://stability-testnet.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=stability_testnet" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=stability_testnet"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for Polygon zkEVM network explorer # Set of ENVs for Polygon zkEVM network explorer
# https://zkevm.blockscout.com # https://zkevm.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=zkevm" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zkevm"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
# Set of ENVs for ZkSync Era network explorer # Set of ENVs for ZkSync Era network explorer
# https://zksync.blockscout.com # https://zksync.blockscout.com
# This is an auto-generated file. To update all values, run "yarn preset:sync --name=zksync" # This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zksync"
# Local ENVs # Local ENVs
NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_PROTOCOL=http
......
...@@ -157,3 +157,12 @@ export const validator: Address = { ...@@ -157,3 +157,12 @@ export const validator: Address = {
watchlist_address_id: null, watchlist_address_id: null,
ens_domain_name: null, ens_domain_name: null,
}; };
export const filecoin = {
...validator,
filecoin: {
actor_type: 'evm' as const,
id: 'f02977693',
robust: 'f410fuiwj6a3yxajbohrl5vu6ns6o2e2jriul52lvzci',
},
};
...@@ -11,6 +11,7 @@ const PRESETS = { ...@@ -11,6 +11,7 @@ const PRESETS = {
eth_goerli: 'https://eth-goerli.blockscout.com', eth_goerli: 'https://eth-goerli.blockscout.com',
eth_sepolia: 'https://eth-sepolia.blockscout.com', eth_sepolia: 'https://eth-sepolia.blockscout.com',
garnet: 'https://explorer.garnetchain.com', garnet: 'https://explorer.garnetchain.com',
filecoin: 'https://filecoin.blockscout.com',
gnosis: 'https://gnosis.blockscout.com', gnosis: 'https://gnosis.blockscout.com',
optimism: 'https://optimism.blockscout.com', optimism: 'https://optimism.blockscout.com',
optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com', optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com',
...@@ -75,7 +76,7 @@ function updateFileContent(envsEntries: Array<[ string, string ]>, presetId: key ...@@ -75,7 +76,7 @@ function updateFileContent(envsEntries: Array<[ string, string ]>, presetId: key
const content = const content =
`# Set of ENVs for ${ chainName } network explorer\n` + `# Set of ENVs for ${ chainName } network explorer\n` +
'# ' + explorerUrl + '\n' + '# ' + explorerUrl + '\n' +
`# This is an auto-generated file. To update all values, run "yarn preset:sync --name=${ presetId }"\n` + `# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=${ presetId }"\n` +
'\n' + '\n' +
'# Local ENVs\n' + '# Local ENVs\n' +
localEnvsContent + '\n' + localEnvsContent + '\n' +
......
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import type { UserTags, AddressImplementation, AddressParam } from './addressParams'; import type { UserTags, AddressImplementation, AddressParam, AddressFilecoinParams } from './addressParams';
import type { Block, EpochRewardsType } from './block'; import type { Block, EpochRewardsType } from './block';
import type { InternalTransaction } from './internalTransaction'; import type { InternalTransaction } from './internalTransaction';
import type { MudWorldSchema, MudWorldTable } from './mudWorlds'; import type { MudWorldSchema, MudWorldTable } from './mudWorlds';
...@@ -11,9 +11,11 @@ export interface Address extends UserTags { ...@@ -11,9 +11,11 @@ export interface Address extends UserTags {
block_number_balance_updated_at: number | null; block_number_balance_updated_at: number | null;
coin_balance: string | null; coin_balance: string | null;
creator_address_hash: string | null; creator_address_hash: string | null;
creator_filecoin_robust_address?: string | null;
creation_tx_hash: string | null; creation_tx_hash: string | null;
exchange_rate: string | null; exchange_rate: string | null;
ens_domain_name: string | null; ens_domain_name: string | null;
filecoin?: AddressFilecoinParams;
// TODO: if we are happy with tabs-counters method, should we delete has_something fields? // TODO: if we are happy with tabs-counters method, should we delete has_something fields?
has_beacon_chain_withdrawals?: boolean; has_beacon_chain_withdrawals?: boolean;
has_decompiled_code: boolean; has_decompiled_code: boolean;
......
...@@ -16,6 +16,30 @@ export interface WatchlistName { ...@@ -16,6 +16,30 @@ export interface WatchlistName {
display_name: string; display_name: string;
} }
export type AddressFilecoinParams = {
actor_type?: FilecoinActorType;
id?: string | null;
robust?: string | null;
}
export type FilecoinActorType =
'account' |
'cron' |
'datacap' |
'eam' |
'ethaccount' |
'evm' |
'init' |
'market' |
'miner' |
'multisig' |
'paych' |
'placeholder' |
'power' |
'reward' |
'system' |
'verifreg';
export interface UserTags { export interface UserTags {
private_tags: Array<AddressTag> | null; private_tags: Array<AddressTag> | null;
watchlist_names: Array<WatchlistName> | null; watchlist_names: Array<WatchlistName> | null;
...@@ -33,6 +57,7 @@ export type AddressParamBasic = { ...@@ -33,6 +57,7 @@ export type AddressParamBasic = {
reputation: number | null; reputation: number | null;
tags: Array<AddressMetadataTagApi>; tags: Array<AddressMetadataTagApi>;
} | null; } | null;
filecoin?: AddressFilecoinParams;
} }
export type AddressParam = UserTags & AddressParamBasic; export type AddressParam = UserTags & AddressParamBasic;
...@@ -67,6 +67,7 @@ export interface SmartContract { ...@@ -67,6 +67,7 @@ export interface SmartContract {
remappings?: Array<string>; remappings?: Array<string>;
}; };
verified_twin_address_hash: string | null; verified_twin_address_hash: string | null;
verified_twin_filecoin_robust_address?: string | null;
proxy_type: SmartContractProxyType | null; proxy_type: SmartContractProxyType | null;
language: string | null; language: string | null;
license_type: SmartContractLicenseType | null; license_type: SmartContractLicenseType | null;
......
...@@ -15,6 +15,7 @@ export interface SearchResultToken { ...@@ -15,6 +15,7 @@ export interface SearchResultToken {
total_supply: string | null; total_supply: string | null;
is_verified_via_admin_panel: boolean; is_verified_via_admin_panel: boolean;
is_smart_contract_verified: boolean; is_smart_contract_verified: boolean;
filecoin_robust_address?: string | null;
} }
export interface SearchResultAddressOrContract { export interface SearchResultAddressOrContract {
...@@ -23,6 +24,7 @@ export interface SearchResultAddressOrContract { ...@@ -23,6 +24,7 @@ export interface SearchResultAddressOrContract {
address: string; address: string;
is_smart_contract_verified: boolean; is_smart_contract_verified: boolean;
certified?: true; certified?: true;
filecoin_robust_address?: string | null;
url?: string; // not used by the frontend, we build the url ourselves url?: string; // not used by the frontend, we build the url ourselves
ens_info?: { ens_info?: {
address_hash: string; address_hash: string;
...@@ -36,6 +38,7 @@ export interface SearchResultDomain { ...@@ -36,6 +38,7 @@ export interface SearchResultDomain {
type: 'ens_domain'; type: 'ens_domain';
name: string | null; name: string | null;
address: string; address: string;
filecoin_robust_address?: string | null;
is_smart_contract_verified: boolean; is_smart_contract_verified: boolean;
url?: string; // not used by the frontend, we build the url ourselves url?: string; // not used by the frontend, we build the url ourselves
ens_info: { ens_info: {
...@@ -49,6 +52,7 @@ export interface SearchResultDomain { ...@@ -49,6 +52,7 @@ export interface SearchResultDomain {
export interface SearchResultLabel { export interface SearchResultLabel {
type: 'label'; type: 'label';
address: string; address: string;
filecoin_robust_address?: string | null;
name: string; name: string;
is_smart_contract_verified: boolean; is_smart_contract_verified: boolean;
url?: string; // not used by the frontend, we build the url ourselves url?: string; // not used by the frontend, we build the url ourselves
......
...@@ -20,6 +20,7 @@ export interface TokenInfo<T extends TokenType = TokenType> { ...@@ -20,6 +20,7 @@ export interface TokenInfo<T extends TokenType = TokenType> {
bridge_type?: string | null; bridge_type?: string | null;
origin_chain_id?: string | null; origin_chain_id?: string | null;
foreign_address?: string | null; foreign_address?: string | null;
filecoin_robust_address?: string | null;
} }
export interface TokenCounters { export interface TokenCounters {
......
...@@ -44,6 +44,17 @@ test.describe('mobile', () => { ...@@ -44,6 +44,17 @@ test.describe('mobile', () => {
}); });
}); });
test('filecoin', async({ render, mockApiResponse, page }) => {
await mockApiResponse('address', addressMock.filecoin, { pathParams: { hash: ADDRESS_HASH } });
await mockApiResponse('address_counters', countersMock.forValidator, { pathParams: { hash: ADDRESS_HASH } });
const component = await render(<AddressDetails addressQuery={{ data: addressMock.filecoin } as AddressQuery}/>, { hooksConfig });
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
}); });
test('contract', async({ render, page, mockApiResponse }) => { test('contract', async({ render, page, mockApiResponse }) => {
...@@ -92,3 +103,15 @@ test('validator', async({ render, mockApiResponse, page }) => { ...@@ -92,3 +103,15 @@ test('validator', async({ render, mockApiResponse, page }) => {
maskColor: pwConfig.maskColor, maskColor: pwConfig.maskColor,
}); });
}); });
test('filecoin', async({ render, mockApiResponse, page }) => {
await mockApiResponse('address', addressMock.filecoin, { pathParams: { hash: ADDRESS_HASH } });
await mockApiResponse('address_counters', countersMock.forValidator, { pathParams: { hash: ADDRESS_HASH } });
const component = await render(<AddressDetails addressQuery={{ data: addressMock.filecoin } as AddressQuery}/>, { hooksConfig });
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
...@@ -10,6 +10,7 @@ import getQueryParamString from 'lib/router/getQueryParamString'; ...@@ -10,6 +10,7 @@ import getQueryParamString from 'lib/router/getQueryParamString';
import AddressCounterItem from 'ui/address/details/AddressCounterItem'; import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning'; import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError'; import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem'; import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
...@@ -22,6 +23,7 @@ import AddressImplementations from './details/AddressImplementations'; ...@@ -22,6 +23,7 @@ import AddressImplementations from './details/AddressImplementations';
import AddressNameInfo from './details/AddressNameInfo'; import AddressNameInfo from './details/AddressNameInfo';
import AddressNetWorth from './details/AddressNetWorth'; import AddressNetWorth from './details/AddressNetWorth';
import AddressSaveOnGas from './details/AddressSaveOnGas'; import AddressSaveOnGas from './details/AddressSaveOnGas';
import FilecoinActorTag from './filecoin/FilecoinActorTag';
import TokenSelect from './tokenSelect/TokenSelect'; import TokenSelect from './tokenSelect/TokenSelect';
import useAddressCountersQuery from './utils/useAddressCountersQuery'; import useAddressCountersQuery from './utils/useAddressCountersQuery';
import type { AddressQuery } from './utils/useAddressQuery'; import type { AddressQuery } from './utils/useAddressQuery';
...@@ -63,6 +65,9 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -63,6 +65,9 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
has_tokens: true, has_tokens: true,
has_token_transfers: true, has_token_transfers: true,
has_validated_blocks: false, has_validated_blocks: false,
filecoin: undefined,
creator_filecoin_robust_address: null,
creator_address_hash: null,
}), [ addressHash ]); }), [ addressHash ]);
// error handling (except 404 codes) // error handling (except 404 codes)
...@@ -83,6 +88,8 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -83,6 +88,8 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
return null; return null;
} }
const creatorAddressHash = data.creator_address_hash;
return ( return (
<> <>
{ addressQuery.isDegradedData && <ServiceDegradationWarning isLoading={ addressQuery.isPlaceholderData } mb={ 6 }/> } { addressQuery.isDegradedData && <ServiceDegradationWarning isLoading={ addressQuery.isPlaceholderData } mb={ 6 }/> }
...@@ -91,9 +98,53 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -91,9 +98,53 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
rowGap={{ base: 1, lg: 3 }} rowGap={{ base: 1, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden" templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden"
> >
{ data.filecoin?.id && (
<>
<DetailsInfoItem.Label
hint="Short identifier of an address that may change with chain state updates"
>
ID
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
<Text>{ data.filecoin.id }</Text>
<CopyToClipboard text={ data.filecoin.id }/>
</DetailsInfoItem.Value>
</>
) }
{ data.filecoin?.actor_type && (
<>
<DetailsInfoItem.Label
hint="Identifies the purpose and behavior of the address on the Filecoin network"
>
Actor
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
<FilecoinActorTag actorType={ data.filecoin.actor_type }/>
</DetailsInfoItem.Value>
</>
) }
{ (data.filecoin?.actor_type === 'evm' || data.filecoin?.actor_type === 'ethaccount') && data?.filecoin?.robust && (
<>
<DetailsInfoItem.Label
hint="0x-style address to which the Filecoin address is assigned by the Ethereum Address Manager"
>
Ethereum Address
</DetailsInfoItem.Label>
<DetailsInfoItem.Value flexWrap="nowrap">
<AddressEntity
address={{ hash: data.hash }}
noIcon
noLink
/>
</DetailsInfoItem.Value>
</>
) }
<AddressNameInfo data={ data } isLoading={ addressQuery.isPlaceholderData }/> <AddressNameInfo data={ data } isLoading={ addressQuery.isPlaceholderData }/>
{ data.is_contract && data.creation_tx_hash && data.creator_address_hash && ( { data.is_contract && data.creation_tx_hash && (creatorAddressHash) && (
<> <>
<DetailsInfoItem.Label <DetailsInfoItem.Label
hint="Transaction and address of creation" hint="Transaction and address of creation"
...@@ -103,7 +154,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -103,7 +154,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<AddressEntity <AddressEntity
address={{ hash: data.creator_address_hash }} address={{ hash: creatorAddressHash, filecoin: { robust: data.creator_filecoin_robust_address } }}
truncation="constant" truncation="constant"
noIcon noIcon
/> />
......
...@@ -72,7 +72,7 @@ const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props) ...@@ -72,7 +72,7 @@ const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props)
<Alert status="warning" whiteSpace="pre-wrap" flexWrap="wrap"> <Alert status="warning" whiteSpace="pre-wrap" flexWrap="wrap">
<span>Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB </span> <span>Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB </span>
<AddressEntity <AddressEntity
address={{ hash: data.verified_twin_address_hash, is_contract: true }} address={{ hash: data.verified_twin_address_hash, filecoin: { robust: data.verified_twin_filecoin_robust_address }, is_contract: true }}
truncation="constant" truncation="constant"
fontSize="sm" fontSize="sm"
fontWeight="500" fontWeight="500"
......
import { Tag } from '@chakra-ui/react';
import React from 'react';
import type { FilecoinActorType } from 'types/api/addressParams';
const ACTOR_TYPES: Record<FilecoinActorType, string> = {
account: 'Account',
cron: 'Scheduled Tasks',
datacap: 'Data Cap Management',
eam: 'Ethereum Address Manager',
ethaccount: 'Ethereum-Compatible Account',
evm: 'Ethereum Virtual Machine',
init: 'Initialization',
market: 'Storage Market',
miner: 'Storage Provider',
multisig: 'Multi-Signature Wallet',
paych: 'Payment Channel',
placeholder: 'Placeholder Address',
power: 'Power Management',
reward: 'Incentives and Rewards',
system: 'System Operations',
verifreg: 'Verification Registry',
};
type Props = {
actorType: FilecoinActorType;
}
const FilecoinActorTag = ({ actorType }: Props) => {
const text = ACTOR_TYPES[actorType];
if (!text) {
return null;
}
return <Tag colorScheme="gray">{ text }</Tag>;
};
export default FilecoinActorTag;
...@@ -346,7 +346,13 @@ const AddressPageContent = () => { ...@@ -346,7 +346,13 @@ const AddressPageContent = () => {
/> />
) } ) }
<AddressEntity <AddressEntity
address={{ ...addressQuery.data, hash: checkSummedHash, name: '', ens_domain_name: '', implementations: null }} address={{
...addressQuery.data,
hash: checkSummedHash,
name: '',
ens_domain_name: '',
implementations: null,
}}
isLoading={ isLoading } isLoading={ isLoading }
fontFamily="heading" fontFamily="heading"
fontSize="lg" fontSize="lg"
...@@ -361,7 +367,7 @@ const AddressPageContent = () => { ...@@ -361,7 +367,7 @@ const AddressPageContent = () => {
{ !isLoading && !addressQuery.data?.is_contract && config.features.account.isEnabled && ( { !isLoading && !addressQuery.data?.is_contract && config.features.account.isEnabled && (
<AddressFavoriteButton hash={ hash } watchListId={ addressQuery.data?.watchlist_address_id }/> <AddressFavoriteButton hash={ hash } watchListId={ addressQuery.data?.watchlist_address_id }/>
) } ) }
<AddressQrCode address={{ hash: checkSummedHash }} isLoading={ isLoading }/> <AddressQrCode address={{ hash: addressQuery.data?.filecoin?.robust ?? checkSummedHash }} isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading }/> <AccountActionsMenu isLoading={ isLoading }/>
<HStack ml="auto" gap={ 2 }/> <HStack ml="auto" gap={ 2 }/>
{ !isLoading && addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled && { !isLoading && addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled &&
......
...@@ -80,6 +80,9 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -80,6 +80,9 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
const shouldHighlightHash = ADDRESS_REGEXP.test(searchTerm); const shouldHighlightHash = ADDRESS_REGEXP.test(searchTerm);
const address = { const address = {
hash: data.address, hash: data.address,
filecoin: {
robust: data.filecoin_robust_address,
},
is_contract: data.type === 'contract', is_contract: data.type === 'contract',
is_verified: data.is_smart_contract_verified, is_verified: data.is_smart_contract_verified,
name: null, name: null,
...@@ -288,7 +291,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -288,7 +291,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
<Grid templateColumns={ templateCols } alignItems="center" gap={ 2 }> <Grid templateColumns={ templateCols } alignItems="center" gap={ 2 }>
<Skeleton isLoaded={ !isLoading } overflow="hidden" display="flex" alignItems="center"> <Skeleton isLoaded={ !isLoading } overflow="hidden" display="flex" alignItems="center">
<Text whiteSpace="nowrap" overflow="hidden"> <Text whiteSpace="nowrap" overflow="hidden">
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address } isTooltipDisabled/>
</Text> </Text>
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Skeleton> </Skeleton>
...@@ -333,7 +336,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -333,7 +336,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
return ( return (
<Flex alignItems="center"> <Flex alignItems="center">
<Box overflow="hidden"> <Box overflow="hidden">
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Flex> </Flex>
...@@ -384,7 +387,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -384,7 +387,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
return ( return (
<Flex alignItems="center" gap={ 3 }> <Flex alignItems="center" gap={ 3 }>
<Box overflow="hidden"> <Box overflow="hidden">
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address }/>
</Box> </Box>
{ {
data.ens_info.names_count > 1 ? data.ens_info.names_count > 1 ?
......
...@@ -77,7 +77,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -77,7 +77,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
<Skeleton isLoaded={ !isLoading } whiteSpace="nowrap" overflow="hidden" display="flex" alignItems="center"> <Skeleton isLoaded={ !isLoading } whiteSpace="nowrap" overflow="hidden" display="flex" alignItems="center">
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }> <Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Skeleton> </Skeleton>
...@@ -100,6 +100,9 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -100,6 +100,9 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
const addressName = data.name || data.ens_info?.name; const addressName = data.name || data.ens_info?.name;
const address = { const address = {
hash: data.address, hash: data.address,
filecoin: {
robust: data.filecoin_robust_address,
},
is_contract: data.type === 'contract', is_contract: data.type === 'contract',
is_verified: data.is_smart_contract_verified, is_verified: data.is_smart_contract_verified,
name: null, name: null,
...@@ -174,7 +177,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -174,7 +177,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
<Flex alignItems="center" overflow="hidden"> <Flex alignItems="center" overflow="hidden">
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }> <Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Flex> </Flex>
...@@ -392,7 +395,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -392,7 +395,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<Td> <Td>
<Flex alignItems="center" overflow="hidden"> <Flex alignItems="center" overflow="hidden">
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }> <Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Flex> </Flex>
......
...@@ -77,7 +77,7 @@ const Icon = (props: IconProps) => { ...@@ -77,7 +77,7 @@ const Icon = (props: IconProps) => {
<Flex marginRight={ styles.marginRight }> <Flex marginRight={ styles.marginRight }>
<AddressIdenticon <AddressIdenticon
size={ props.size === 'lg' ? 30 : 20 } size={ props.size === 'lg' ? 30 : 20 }
hash={ props.address.hash } hash={ props.address.filecoin?.robust ?? props.address.hash }
/> />
</Flex> </Flex>
); );
...@@ -99,7 +99,7 @@ const Content = chakra((props: ContentProps) => { ...@@ -99,7 +99,7 @@ const Content = chakra((props: ContentProps) => {
const label = ( const label = (
<VStack gap={ 0 } py={ 1 } color="inherit"> <VStack gap={ 0 } py={ 1 } color="inherit">
<Box fontWeight={ 600 } whiteSpace="pre-wrap" wordBreak="break-word">{ nameText }</Box> <Box fontWeight={ 600 } whiteSpace="pre-wrap" wordBreak="break-word">{ nameText }</Box>
<Box whiteSpace="pre-wrap" wordBreak="break-word">{ props.address.hash }</Box> <Box whiteSpace="pre-wrap" wordBreak="break-word">{ props.address.filecoin?.robust ?? props.address.hash }</Box>
</VStack> </VStack>
); );
...@@ -115,7 +115,7 @@ const Content = chakra((props: ContentProps) => { ...@@ -115,7 +115,7 @@ const Content = chakra((props: ContentProps) => {
return ( return (
<EntityBase.Content <EntityBase.Content
{ ...props } { ...props }
text={ props.address.hash } text={ props.address.filecoin?.robust ?? props.address.hash }
/> />
); );
}); });
...@@ -126,7 +126,7 @@ const Copy = (props: CopyProps) => { ...@@ -126,7 +126,7 @@ const Copy = (props: CopyProps) => {
return ( return (
<EntityBase.Copy <EntityBase.Copy
{ ...props } { ...props }
text={ props.address.hash } text={ props.address.filecoin?.robust ?? props.address.hash }
/> />
); );
}; };
......
...@@ -46,7 +46,7 @@ const AddressEntityContentProxy = (props: ContentProps) => { ...@@ -46,7 +46,7 @@ const AddressEntityContentProxy = (props: ContentProps) => {
Proxy contract Proxy contract
{ props.address.name ? ` (${ props.address.name })` : '' } { props.address.name ? ` (${ props.address.name })` : '' }
</Box> </Box>
<AddressEntity address={{ hash: props.address.hash }} noLink noIcon noHighlight justifyContent="center"/> <AddressEntity address={{ hash: props.address.hash, filecoin: props.address.filecoin }} noLink noIcon noHighlight justifyContent="center"/>
<Box fontWeight={ 600 } mt={ 2 }> <Box fontWeight={ 600 } mt={ 2 }>
Implementation{ implementations.length > 1 ? 's' : '' } Implementation{ implementations.length > 1 ? 's' : '' }
{ implementationName ? ` (${ implementationName })` : '' } { implementationName ? ` (${ implementationName })` : '' }
......
...@@ -52,7 +52,7 @@ const SearchBarSuggestAddress = ({ data, isMobile, searchTerm }: Props) => { ...@@ -52,7 +52,7 @@ const SearchBarSuggestAddress = ({ data, isMobile, searchTerm }: Props) => {
{ data.certified && <ContractCertifiedLabel boxSize={ 5 } iconSize={ 5 } ml={ 1 }/> } { data.certified && <ContractCertifiedLabel boxSize={ 5 } iconSize={ 5 } ml={ 1 }/> }
</Flex> </Flex>
); );
const addressEl = <HashStringShortenDynamic hash={ data.address } isTooltipDisabled/>; const addressEl = <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address } isTooltipDisabled/>;
if (isMobile) { if (isMobile) {
return ( return (
......
...@@ -34,7 +34,7 @@ const SearchBarSuggestDomain = ({ data, isMobile, searchTerm }: Props) => { ...@@ -34,7 +34,7 @@ const SearchBarSuggestDomain = ({ data, isMobile, searchTerm }: Props) => {
whiteSpace="nowrap" whiteSpace="nowrap"
variant="secondary" variant="secondary"
> >
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address } isTooltipDisabled/>
</Text> </Text>
); );
......
...@@ -33,7 +33,7 @@ const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => { ...@@ -33,7 +33,7 @@ const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => {
whiteSpace="nowrap" whiteSpace="nowrap"
variant="secondary" variant="secondary"
> >
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address } isTooltipDisabled/>
</Text> </Text>
); );
......
...@@ -30,7 +30,7 @@ const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => { ...@@ -30,7 +30,7 @@ const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => {
const address = ( const address = (
<Text variant="secondary" whiteSpace="nowrap" overflow="hidden"> <Text variant="secondary" whiteSpace="nowrap" overflow="hidden">
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.filecoin_robust_address || data.address } isTooltipDisabled/>
</Text> </Text>
); );
......
...@@ -28,6 +28,9 @@ const TokenInstanceCreatorAddress = ({ hash }: Props) => { ...@@ -28,6 +28,9 @@ const TokenInstanceCreatorAddress = ({ hash }: Props) => {
const creatorAddress = { const creatorAddress = {
hash: addressQuery.data.creator_address_hash, hash: addressQuery.data.creator_address_hash,
filecoin: {
robust: addressQuery.data.creator_filecoin_robust_address,
},
is_contract: false, is_contract: false,
implementations: null, implementations: null,
}; };
......
...@@ -32,6 +32,7 @@ const TokensTableItem = ({ ...@@ -32,6 +32,7 @@ const TokensTableItem = ({
const { const {
address, address,
filecoin_robust_address: filecoinRobustAddress,
exchange_rate: exchangeRate, exchange_rate: exchangeRate,
type, type,
holders, holders,
...@@ -70,7 +71,7 @@ const TokensTableItem = ({ ...@@ -70,7 +71,7 @@ const TokensTableItem = ({
</Grid> </Grid>
<Flex justifyContent="space-between" alignItems="center" width="150px" ml={ 7 } mt={ -2 }> <Flex justifyContent="space-between" alignItems="center" width="150px" ml={ 7 } mt={ -2 }>
<AddressEntity <AddressEntity
address={{ hash: address }} address={{ hash: address, filecoin: { robust: filecoinRobustAddress } }}
isLoading={ isLoading } isLoading={ isLoading }
truncation="constant" truncation="constant"
noIcon noIcon
......
...@@ -32,6 +32,7 @@ const TokensTableItem = ({ ...@@ -32,6 +32,7 @@ const TokensTableItem = ({
const { const {
address, address,
filecoin_robust_address: filecoinRobustAddress,
exchange_rate: exchangeRate, exchange_rate: exchangeRate,
type, type,
holders, holders,
...@@ -45,6 +46,9 @@ const TokensTableItem = ({ ...@@ -45,6 +46,9 @@ const TokensTableItem = ({
const tokenAddress: AddressEntityProps['address'] = { const tokenAddress: AddressEntityProps['address'] = {
hash: address, hash: address,
filecoin: {
robust: filecoinRobustAddress,
},
name: '', name: '',
is_contract: true, is_contract: true,
is_verified: false, is_verified: false,
......
...@@ -47,9 +47,9 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => { ...@@ -47,9 +47,9 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => {
{ data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } mx={ 2 }/> } { data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } mx={ 2 }/> }
</Flex> </Flex>
<Skeleton isLoaded={ !isLoading } color="text_secondary" ml="auto"> <Skeleton isLoaded={ !isLoading } color="text_secondary" ml="auto">
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/> <HashStringShorten hash={ data.address.filecoin?.robust ?? data.address.hash } isTooltipDisabled/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.address.hash } isLoading={ isLoading }/> <CopyToClipboard text={ data.address.filecoin?.robust ?? data.address.hash } isLoading={ isLoading }/>
</Flex> </Flex>
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Balance { currencyUnits.ether }</Skeleton> <Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Balance { currencyUnits.ether }</Skeleton>
......
...@@ -46,9 +46,9 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => { ...@@ -46,9 +46,9 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => {
</Flex> </Flex>
<Flex alignItems="center" ml={ 7 }> <Flex alignItems="center" ml={ 7 }>
<Skeleton isLoaded={ !isLoading } color="text_secondary" my={ 1 }> <Skeleton isLoaded={ !isLoading } color="text_secondary" my={ 1 }>
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/> <HashStringShorten hash={ data.address.filecoin?.robust ?? data.address.hash } isTooltipDisabled/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.address.hash } isLoading={ isLoading }/> <CopyToClipboard text={ data.address.filecoin?.robust ?? data.address.hash } isLoading={ isLoading }/>
</Flex> </Flex>
</Td> </Td>
<Td isNumeric> <Td isNumeric>
......
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