@@ -1,22 +1,24 @@
|
||||
import type { Feature } from './types';
|
||||
import type { MultichainProviderConfig } from 'types/client/multichainProviderConfig';
|
||||
import type { MultichainProviderConfig, MultichainProviderConfigParsed } from 'types/client/multichainProviderConfig';
|
||||
|
||||
import { getEnvValue, parseEnvJson } from '../utils';
|
||||
import marketplace from './marketplace';
|
||||
|
||||
const value = parseEnvJson<MultichainProviderConfig>(getEnvValue('NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG'));
|
||||
const value = parseEnvJson<Array<MultichainProviderConfig>>(getEnvValue('NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG'));
|
||||
|
||||
const title = 'Multichain balance';
|
||||
|
||||
const config: Feature<{name: string; logoUrl?: string; urlTemplate: string; dappId?: string }> = (() => {
|
||||
const config: Feature<{ providers: Array<MultichainProviderConfigParsed> }> = (() => {
|
||||
if (value) {
|
||||
return Object.freeze({
|
||||
title,
|
||||
isEnabled: true,
|
||||
name: value.name,
|
||||
logoUrl: value.logo,
|
||||
urlTemplate: value.url_template,
|
||||
dappId: marketplace.isEnabled ? value.dapp_id : undefined,
|
||||
providers: value.map((provider) => ({
|
||||
name: provider.name,
|
||||
logoUrl: provider.logo,
|
||||
urlTemplate: provider.url_template,
|
||||
dappId: marketplace.isEnabled ? provider.dapp_id : undefined,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6u
|
||||
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
|
||||
@@ -39,7 +39,7 @@ NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKj
|
||||
NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}, {'name': 'zerion2', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'dapp_id': 'smol-refuel', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&utm_medium=address&disableBridges=true', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
|
||||
|
||||
@@ -38,7 +38,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6u
|
||||
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
|
||||
@@ -45,7 +45,7 @@ NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKj
|
||||
NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/refs/heads/marketplace-graph-test/test-configs/marketplace-graph-links.json
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
|
||||
@@ -39,7 +39,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6u
|
||||
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata-test.k8s-dev.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens-rs-test.k8s-dev.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/blocks','/apps']
|
||||
NEXT_PUBLIC_NAVIGATION_LAYOUT=horizontal
|
||||
|
||||
@@ -39,7 +39,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6u
|
||||
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
|
||||
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
|
||||
@@ -27,7 +27,7 @@ NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
|
||||
NEXT_PUBLIC_LOGOUT_URL=https://zksync.us.auth0.com/v2/logout
|
||||
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
|
||||
NEXT_PUBLIC_METASUITES_ENABLED=true
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
|
||||
|
||||
@@ -56,5 +56,5 @@ NEXT_PUBLIC_ROLLUP_TYPE=optimistic
|
||||
NEXT_PUBLIC_STATS_API_HOST=https://stats-l2-zora-mainnet.k8s-prod-1.blockscout.com
|
||||
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
|
||||
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_ADDRESS_USERNAME_TAG={'api_url_template': 'https://api.zora.co/discover/user/{address}', 'tag_link_template': 'httpszora.co/{username}', 'tag_icon': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zora.svg', 'tag_bg_color': 'rgba(0,0,0)', 'tag_text_color': 'rgba(255,255,255)'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_ADDRESS_USERNAME_TAG={'api_url_template': 'https://api.zora.co/discover/user/{address}', 'tag_link_template': 'httpszora.co/{username}', 'tag_icon': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zora.svg', 'tag_bg_color': 'rgba(0,0,0)', 'tag_text_color': 'rgba(255,255,255)'}
|
||||
|
||||
@@ -530,6 +530,13 @@ const deFiDropdownItemSchema: yup.ObjectSchema<DeFiDropdownItem> = yup
|
||||
return Boolean(value.dappId) || Boolean(value.url);
|
||||
}) as yup.ObjectSchema<DeFiDropdownItem>;
|
||||
|
||||
const multichainProviderConfigSchema: yup.ObjectSchema<MultichainProviderConfig> = yup.object({
|
||||
name: yup.string().required(),
|
||||
url_template: yup.string().required(),
|
||||
logo: yup.string().required(),
|
||||
dapp_id: yup.string(),
|
||||
});
|
||||
|
||||
const schema = yup
|
||||
.object()
|
||||
.noUnknown(true, (params) => {
|
||||
@@ -768,18 +775,10 @@ const schema = yup
|
||||
NEXT_PUBLIC_HAS_USER_OPS: yup.boolean(),
|
||||
NEXT_PUBLIC_METASUITES_ENABLED: yup.boolean(),
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG: yup
|
||||
.mixed()
|
||||
.test('shape', 'Invalid schema were provided for NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG, it should have name and url template', (data) => {
|
||||
const isUndefined = data === undefined;
|
||||
const valueSchema = yup.object<MultichainProviderConfig>().transform(replaceQuotes).json().shape({
|
||||
name: yup.string().required(),
|
||||
url_template: yup.string().required(),
|
||||
logo: yup.string(),
|
||||
dapp_id: yup.string(),
|
||||
});
|
||||
|
||||
return isUndefined || valueSchema.isValidSync(data);
|
||||
}),
|
||||
.array()
|
||||
.transform(replaceQuotes)
|
||||
.json()
|
||||
.of(multichainProviderConfigSchema),
|
||||
NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG: yup
|
||||
.mixed()
|
||||
.test('shape', 'Invalid schema were provided for NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG, it should have name and url template', (data) => {
|
||||
|
||||
@@ -83,6 +83,6 @@ NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false
|
||||
NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket']
|
||||
NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=stability
|
||||
NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'uniswap'},{'text':'Payment link','icon':'payment_link','url':'https://example.com'}]
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
|
||||
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
|
||||
NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'dapp_id': 'smol-refuel', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&utm_medium=address&disableBridges=true', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
|
||||
NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true
|
||||
|
||||
@@ -747,7 +747,7 @@ If the feature is enabled, a Multichain balance button will be displayed on the
|
||||
|
||||
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG | `{ name: string; url_template: string; dapp_id?: string; logo?: string }` | Multichain portfolio application config See [below](#multichain-button-configuration-properties) | - | - | `{ name: 'zerion', url_template: 'https://app.zerion.io/{address}/overview', logo: 'https://example.com/icon.svg'` | v1.31.0+ |
|
||||
| NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG | `[{ name: string; url_template: string; dapp_id?: string; logo: string }]` | Multichain portfolio application config See [below](#multichain-button-configuration-properties) | - | - | `[{ name: 'zerion', url_template: 'https://app.zerion.io/{address}/overview', logo: 'https://example.com/icon.svg'}]` | v1.31.0+ |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,5 +2,12 @@ export type MultichainProviderConfig = {
|
||||
name: string;
|
||||
dapp_id?: string;
|
||||
url_template: string;
|
||||
logo?: string;
|
||||
logo: string;
|
||||
};
|
||||
|
||||
export type MultichainProviderConfigParsed = {
|
||||
name: string;
|
||||
logoUrl: string;
|
||||
urlTemplate: string;
|
||||
dappId?: string;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { Image, Tooltip } from '@chakra-ui/react';
|
||||
import _capitalize from 'lodash/capitalize';
|
||||
import React from 'react';
|
||||
|
||||
import type { MultichainProviderConfigParsed } from 'types/client/multichainProviderConfig';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import LinkExternal from 'ui/shared/links/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/links/LinkInternal';
|
||||
|
||||
const TEMPLATE_ADDRESS = '{address}';
|
||||
|
||||
type Props = {
|
||||
hasSingleProvider: boolean;
|
||||
item: MultichainProviderConfigParsed;
|
||||
addressHash: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const AddressMultichainButton = ({ item, addressHash, onClick, hasSingleProvider }: Props) => {
|
||||
|
||||
const buttonIcon = <Image src={ item.logoUrl } alt={ item.name } boxSize={ 5 } mr={ hasSingleProvider ? 2 : 0 } borderRadius="4px" overflow="hidden"/>;
|
||||
|
||||
const buttonContent = hasSingleProvider ? (
|
||||
<>
|
||||
{ buttonIcon }
|
||||
{ _capitalize(item.name) }
|
||||
</>
|
||||
) : (
|
||||
<Tooltip label={ _capitalize(item.name) }>{ buttonIcon }</Tooltip>
|
||||
);
|
||||
|
||||
const linkProps = {
|
||||
variant: hasSingleProvider ? 'subtle' as const : undefined,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: 'sm',
|
||||
lineHeight: 5,
|
||||
fontWeight: 500,
|
||||
onClick,
|
||||
};
|
||||
|
||||
try {
|
||||
const portfolioUrlString = item.urlTemplate.replace(TEMPLATE_ADDRESS, addressHash);
|
||||
const portfolioUrl = new URL(portfolioUrlString);
|
||||
portfolioUrl.searchParams.append('utm_source', 'blockscout');
|
||||
portfolioUrl.searchParams.append('utm_medium', 'address');
|
||||
const dappId = item.dappId;
|
||||
return typeof dappId === 'string' ? (
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/apps/[id]', query: { id: dappId, url: portfolioUrl.toString() } }) }
|
||||
{ ...linkProps }
|
||||
>
|
||||
{ buttonContent }
|
||||
</LinkInternal>
|
||||
) : (
|
||||
<LinkExternal
|
||||
href={ portfolioUrl.toString() }
|
||||
{ ...linkProps }
|
||||
>
|
||||
{ buttonContent }
|
||||
</LinkExternal>
|
||||
);
|
||||
} catch (error) {}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default AddressMultichainButton;
|
||||
@@ -23,11 +23,11 @@ test('base view', async({ render }) => {
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('with multichain button internal +@dark-mode', async({ render, mockEnvs, mockAssetResponse }) => {
|
||||
test('with single multichain button internal +@dark-mode', async({ render, mockEnvs, mockAssetResponse }) => {
|
||||
await mockEnvs([
|
||||
[
|
||||
'NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG',
|
||||
`{"name": "duck", "dapp_id": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ],
|
||||
`[{"name": "duck", "dapp_id": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}]` ],
|
||||
]);
|
||||
await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg');
|
||||
|
||||
@@ -36,9 +36,23 @@ test('with multichain button internal +@dark-mode', async({ render, mockEnvs, mo
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('with multichain button external', async({ render, mockEnvs, mockAssetResponse }) => {
|
||||
test('with single multichain button external', async({ render, mockEnvs, mockAssetResponse }) => {
|
||||
await mockEnvs([
|
||||
[ 'NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG', `{"name": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ],
|
||||
[ 'NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG', `[{"name": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}]` ],
|
||||
]);
|
||||
await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg');
|
||||
|
||||
const component = await render(<AddressNetWorth addressData={ addressMock.eoa } addressHash={ ADDRESS_HASH }/>);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('with two multichain button external', async({ render, mockEnvs, mockAssetResponse }) => {
|
||||
await mockEnvs([
|
||||
[ 'NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG', `[
|
||||
{"name": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"},
|
||||
{"name": "duck2", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}
|
||||
]` ],
|
||||
]);
|
||||
await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg');
|
||||
|
||||
@@ -51,7 +65,7 @@ test('with multichain button internal small screen', async({ render, mockEnvs, m
|
||||
await mockEnvs([
|
||||
[
|
||||
'NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG',
|
||||
`{"name": "duck", "dapp_id": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ],
|
||||
`[{"name": "duck", "dapp_id": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}]` ],
|
||||
]);
|
||||
await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg');
|
||||
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
import { Image, Skeleton, Text, Flex } from '@chakra-ui/react';
|
||||
import _capitalize from 'lodash/capitalize';
|
||||
import { Skeleton, Text, Flex } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { Address } from 'types/api/address';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import getCurrencyValue from 'lib/getCurrencyValue';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import LinkExternal from 'ui/shared/links/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/links/LinkInternal';
|
||||
import TextSeparator from 'ui/shared/TextSeparator';
|
||||
|
||||
import { getTokensTotalInfo } from '../utils/tokenUtils';
|
||||
import useFetchTokens from '../utils/useFetchTokens';
|
||||
|
||||
const TEMPLATE_ADDRESS = '{address}';
|
||||
import AddressMultichainButton from './AddressMultichainButton';
|
||||
|
||||
const multichainFeature = config.features.multichainButton;
|
||||
|
||||
@@ -46,58 +40,30 @@ const AddressNetWorth = ({ addressData, isLoading, addressHash }: Props) => {
|
||||
mixpanel.logEvent(mixpanel.EventTypes.BUTTON_CLICK, { Content: 'Multichain', Source: 'address' });
|
||||
}, []);
|
||||
|
||||
let multichainItem = null;
|
||||
let multichainItems = null;
|
||||
|
||||
if (multichainFeature.isEnabled && !addressData?.is_contract) {
|
||||
const buttonContent = (
|
||||
const { providers } = multichainFeature;
|
||||
const hasSingleProvider = providers.length === 1;
|
||||
|
||||
multichainItems = (
|
||||
<>
|
||||
{ multichainFeature.logoUrl &&
|
||||
<Image src={ multichainFeature.logoUrl } alt={ multichainFeature.name } boxSize={ 5 } mr={ 2 } borderRadius="4px" overflow="hidden"/>
|
||||
}
|
||||
{ _capitalize(multichainFeature.name) }</>
|
||||
<TextSeparator mx={ 0 } color="gray.500"/>
|
||||
<Flex alignItems="center" gap={ 2 }>
|
||||
<Text>Multichain</Text>
|
||||
{ providers.map((item) => (
|
||||
<AddressMultichainButton
|
||||
key={ item.name }
|
||||
item={ item }
|
||||
addressHash={ addressHash }
|
||||
onClick={ onMultichainClick }
|
||||
hasSingleProvider={ hasSingleProvider }
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
|
||||
const linkProps = {
|
||||
variant: 'subtle' as const,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: 'sm',
|
||||
lineHeight: 5,
|
||||
fontWeight: 500,
|
||||
onClick: onMultichainClick,
|
||||
};
|
||||
|
||||
try {
|
||||
const portfolioUrlString = multichainFeature.urlTemplate.replace(TEMPLATE_ADDRESS, addressHash);
|
||||
const portfolioUrl = new URL(portfolioUrlString);
|
||||
portfolioUrl.searchParams.append('utm_source', 'blockscout');
|
||||
portfolioUrl.searchParams.append('utm_medium', 'address');
|
||||
const dappId = multichainFeature.dappId;
|
||||
multichainItem = (
|
||||
<>
|
||||
<TextSeparator mx={ 0 } color="gray.500"/>
|
||||
<Flex alignItems="center" gap={ 2 }>
|
||||
<Text>Multichain</Text>
|
||||
{ typeof dappId === 'string' ? (
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/apps/[id]', query: { id: dappId, url: portfolioUrl.toString() } }) }
|
||||
{ ...linkProps }
|
||||
>
|
||||
{ buttonContent }
|
||||
</LinkInternal>
|
||||
) : (
|
||||
<LinkExternal
|
||||
href={ portfolioUrl.toString() }
|
||||
{ ...linkProps }
|
||||
>
|
||||
{ buttonContent }
|
||||
</LinkExternal>
|
||||
) }
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
} catch (error) {}
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -105,7 +71,7 @@ const AddressNetWorth = ({ addressData, isLoading, addressHash }: Props) => {
|
||||
<Text>
|
||||
{ (isError || !addressData?.exchange_rate) ? 'N/A' : `${ prefix }$${ totalUsd.toFormat(2) }` }
|
||||
</Text>
|
||||
{ multichainItem }
|
||||
{ multichainItems }
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
|
Before Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.1 KiB |