diff --git a/configs/app/features/multichainButton.ts b/configs/app/features/multichainButton.ts index 3d52d466bc..d513595577 100644 --- a/configs/app/features/multichainButton.ts +++ b/configs/app/features/multichainButton.ts @@ -2,12 +2,13 @@ import type { Feature } from './types'; import type { MultichainProviderConfig } from 'types/client/multichainProviderConfig'; import { getEnvValue, parseEnvJson } from '../utils'; +import marketplace from './marketplace'; const value = parseEnvJson(getEnvValue('NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG')); const title = 'Multichain button'; -const config: Feature<{name: string; logoUrl?: string; url_template: string }> = (() => { +const config: Feature<{name: string; logoUrl?: string; url_template: string; dapp_id?: string }> = (() => { if (value) { return Object.freeze({ title, @@ -15,6 +16,7 @@ const config: Feature<{name: string; logoUrl?: string; url_template: string }> = name: value.name, logoUrl: value.logo, url_template: value.url_template, + dapp_id: marketplace.isEnabled ? value.dapp_id : undefined, }); } diff --git a/configs/envs/.env.eth b/configs/envs/.env.eth index b31e1d8745..2584d493e4 100644 --- a/configs/envs/.env.eth +++ b/configs/envs/.env.eth @@ -53,9 +53,11 @@ NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blocksc NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true -NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG={'name': 'zerion', 'url_template': '/apps/zerion/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'} +NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG={'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'} #meta NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=true +NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx + diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index c88d230189..01944b0661 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -623,12 +623,13 @@ const schema = yup NEXT_PUBLIC_SWAP_BUTTON_URL: yup.string(), NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG: yup .mixed() - .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG, it should have name and url props', (data) => { + .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG, it should have name and url url_template', (data) => { const isUndefined = data === undefined; const valueSchema = yup.object().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); diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index c326068bb8..7b63a1aaac 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -74,5 +74,5 @@ NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket'] NEXT_PUBLIC_SWAP_BUTTON_URL=uniswap NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=stability -NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG={'name': 'zerion', 'url_template': '/apps/zerion/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'} +NEXT_PUBLIC_MULTICHAIN_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'} diff --git a/docs/ENVS.md b/docs/ENVS.md index 51ac980297..3a087fb348 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -686,7 +686,7 @@ If the feature is enabled, a Multichain balance button will be displayed on the | Variable | Type| Description | Compulsoriness | Default value | Example value | | --- | --- | --- | --- | --- | --- | -| NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG | `{ name: string; url_template: string; logo?: string }` | Multichain portfolio application config See [below](#multichain-button-configuration-properties) | - | - | `{ name: 'zerion', url_template: '/apps/zerion/{address}/overview', logo: 'https://example.com/icon.svg'` | +| NEXT_PUBLIC_MULTICHAIN_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'` |   @@ -695,7 +695,8 @@ If the feature is enabled, a Multichain balance button will be displayed on the | Variable | Type| Description | Compulsoriness | Default value | Example value | | --- | --- | --- | --- | --- | --- | | name | `string` | Multichain portfolio application name | Required | - | `zerion` | -| url_template | `string` | Absolute (for external links) or relative (for internal links) path template to the portfolio. Should be a template with `{address}` variable | Required | - | `/apps/zerion/{address}/overview` | +| url_template | `string` | Url template to the portfolio. Should be a template with `{address}` variable | Required | - | `https://app.zerion.io/{address}/overview` | +| dapp_id | `string` | Set for open a Blockscout dapp page with the portfolio instead of opening external app page | - | - | `zerion` | | logo | `string` | Multichain portfolio application logo (.svg) url | - | - | `https://example.com/icon.svg` |   diff --git a/types/client/multichainProviderConfig.ts b/types/client/multichainProviderConfig.ts index fbec165ef3..fbdced386f 100644 --- a/types/client/multichainProviderConfig.ts +++ b/types/client/multichainProviderConfig.ts @@ -1,5 +1,6 @@ export type MultichainProviderConfig = { name: string; + dapp_id?: string; url_template: string; logo?: string; }; diff --git a/ui/address/details/AddressNetWorth.pw.tsx b/ui/address/details/AddressNetWorth.pw.tsx index f9102b7086..ea955c8091 100644 --- a/ui/address/details/AddressNetWorth.pw.tsx +++ b/ui/address/details/AddressNetWorth.pw.tsx @@ -29,7 +29,7 @@ test('base view', async({ mount }) => { test('with multichain button internal +@dark-mode', async({ mount, mockEnvs, mockAssetResponse }) => { await mockEnvs([ - [ 'NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG', `{"name": "zerion", "url_template": "/apps/zerion/{address}/overview", "logo": "${ ICON_URL }"}` ], + [ 'NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG', `{"name": "duck", "dapp_id": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ], ]); await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg'); @@ -44,7 +44,7 @@ test('with multichain button internal +@dark-mode', async({ mount, mockEnvs, moc test('with multichain button external', async({ mount, mockEnvs, mockAssetResponse }) => { await mockEnvs([ - [ 'NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG', `{"name": "zerion", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ], + [ 'NEXT_PUBLIC_MULTICHAIN_PROVIDER_CONFIG', `{"name": "duck", "url_template": "https://duck.url/{address}", "logo": "${ ICON_URL }"}` ], ]); await mockAssetResponse(ICON_URL, './playwright/mocks/image_svg.svg'); diff --git a/ui/address/details/AddressNetWorth.tsx b/ui/address/details/AddressNetWorth.tsx index c4c66046a5..10ef92febb 100644 --- a/ui/address/details/AddressNetWorth.tsx +++ b/ui/address/details/AddressNetWorth.tsx @@ -4,10 +4,11 @@ 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 * as regexp from 'lib/regexp'; import LinkExternal from 'ui/shared/links/LinkExternal'; import LinkInternal from 'ui/shared/links/LinkInternal'; import TextSeparator from 'ui/shared/TextSeparator'; @@ -65,31 +66,31 @@ const AddressNetWorth = ({ addressData, isLoading, addressHash }: Props) => { onClick: onMultichainClick, }; - const urlString = multichainFeature.url_template.replace(TEMPLATE_ADDRESS, addressHash); - const isExternal = regexp.URL_PREFIX.test(urlString); - const url = isExternal ? new URL(urlString) : new URL(urlString, config.app.baseUrl); + const portfolioUrlString = multichainFeature.url_template.replace(TEMPLATE_ADDRESS, addressHash); + const portfolioUrl = new URL(portfolioUrlString); + portfolioUrl.searchParams.append('utm_source', 'blockscout'); + portfolioUrl.searchParams.append('utm_medium', 'address'); - url.searchParams.append('utm_source', 'blockscout'); - url.searchParams.append('utm_medium', 'address'); + const dappId = multichainFeature.dapp_id; multichainItem = ( <> Multichain - { isExternal ? ( - { buttonContent } - + ) : ( - { buttonContent } - + ) } );