Skip to content

Commit

Permalink
Merge pull request #1492 from oasisprotocol/lw/abi-playground
Browse files Browse the repository at this point in the history
Link to ABI playground from verified contracts
  • Loading branch information
lukaw3d authored Aug 16, 2024
2 parents 5cb33ab + b2491de commit ff75d5b
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 49 deletions.
1 change: 1 addition & 0 deletions .changelog/1492.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Link to ABI playground from verified contracts
12 changes: 6 additions & 6 deletions playwright/tests/accounts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ async function setup(page: Page) {
// Don't respond
},
)
await page.route('**/v1/', route => {
// Don't respond
})
await page.route('**/v1/sapphire/status', route => {
// Don't respond
})
await page.route(
url => url.href.includes('.oasis.io/v1/'),
route => {
// Don't respond
},
)
await page.route(
'**/v1/sapphire/transactions?limit=10&offset=0&rel=oasis1qq2v39p9fqk997vk6742axrzqyu9v2ncyuqt8uek',
route => {
Expand Down
15 changes: 9 additions & 6 deletions playwright/tests/analytics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import '../../src/types/global.d.ts'
import { Page, expect, test } from '@playwright/test'

async function setup(page: Page, mode: 'allow-matomo-lib' | 'block-matomo-lib') {
await page.route('**/v1/', route => {
// Don't respond
})
await page.route(
url => url.href.includes('.oasis.io/v1/'),
route => {
// Don't respond
},
)
await page.route('https://matomo.oasis.io/matomo.php?**', route => {
// Don't send tracked events
})
Expand Down Expand Up @@ -41,12 +44,12 @@ test.describe('analytics', () => {

await page.getByRole('button', { name: 'Privacy Settings' }).click()
await page.getByRole('button', { name: 'Accept' }).click()
await page.waitForTimeout(1)
await page.waitForTimeout(100)
expect(getMatomoRequests()).toHaveLength(2) // Tracked

await page.getByRole('link', { name: 'Blocks' }).first().click()
await page.waitForRequest('https://matomo.oasis.io/matomo.php?**') // Debounced
await page.waitForTimeout(1)
await page.waitForTimeout(100)
expect(getMatomoRequests()).toHaveLength(3) // Tracked
})

Expand Down Expand Up @@ -78,7 +81,7 @@ test.describe('analytics', () => {
await test.step('consent', async () => {
expect(getMatomoRequests()).toHaveLength(1) // Loaded library
await page.getByRole('button', { name: 'Accept' }).click()
await page.waitForTimeout(1)
await page.waitForTimeout(100)
expect(getMatomoRequests()).toHaveLength(2) // Tracked
})

Expand Down
12 changes: 6 additions & 6 deletions playwright/tests/getPreciseNumberFormat.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ async function setup(page: Page, balance: string, decimals: number) {
// Don't respond
},
)
await page.route('**/v1/', route => {
// Don't respond
})
await page.route('**/v1/sapphire/status', route => {
// Don't respond
})
await page.route(
url => url.href.includes('.oasis.io/v1/'),
route => {
// Don't respond
},
)

await page.route('**/v1/sapphire/accounts/oasis1qq2v39p9fqk997vk6742axrzqyu9v2ncyuqt8uek', route => {
route.fulfill({
Expand Down
92 changes: 67 additions & 25 deletions src/app/components/ContractVerificationIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { COLORS } from '../../../styles/theme/colors'
import Link from '@mui/material/Link'
import Typography from '@mui/material/Typography'
import Skeleton from '@mui/material/Skeleton'
import { RuntimeAccount } from '../../../oasis-nexus/api'
import { Layer, RuntimeAccount } from '../../../oasis-nexus/api'
import { SearchScope } from '../../../types/searchScope'
import { Network } from '../../../types/network'
import * as externalLinks from '../../utils/externalLinks'

type VerificationStatus = 'verified' | 'unverified'

Expand Down Expand Up @@ -52,7 +55,7 @@ const StyledPill = styled(Box, {
})

type ContractVerificationIconProps = {
account: Pick<RuntimeAccount, 'address_eth' | 'evm_contract'> | undefined
account: Pick<RuntimeAccount, 'address_eth' | 'evm_contract' | 'network' | 'layer'> | undefined
noLink?: boolean
}

Expand All @@ -71,14 +74,15 @@ export const ContractVerificationIcon: FC<ContractVerificationIconProps> = ({ ac
const verified = !!account.evm_contract?.verification
const address_eth = account.address_eth!

return <VerificationIcon address_eth={address_eth} verified={verified} noLink={noLink} />
return <VerificationIcon address_eth={address_eth} scope={account} verified={verified} noLink={noLink} />
}

export const VerificationIcon: FC<{ address_eth: string; verified: boolean; noLink?: boolean }> = ({
address_eth,
verified,
noLink = false,
}) => {
export const VerificationIcon: FC<{
address_eth: string
scope: SearchScope
verified: boolean
noLink?: boolean
}> = ({ address_eth, scope, verified, noLink = false }) => {
const { t } = useTranslation()
const [explainDelay, setExplainDelay] = useState(false)

Expand All @@ -87,15 +91,32 @@ export const VerificationIcon: FC<{ address_eth: string; verified: boolean; noLi
verified: t('contract.verification.isVerified'),
unverified: t('contract.verification.isNotVerified'),
}
const linkProps = {
href: `https://sourcify.dev/#/lookup/${address_eth}`,
const sourcifyLinkProps = {
href: `${externalLinks.dapps.sourcifyRoot}#/lookup/${address_eth}`,
rel: 'noopener noreferrer',
target: '_blank',
sx: { fontWeight: 400, color: 'inherit', textDecoration: 'underline' },
onClick: verified ? undefined : () => setExplainDelay(true),
}
const Component = noLink ? Box : Link
const componentProps = noLink ? {} : linkProps
const componentProps = noLink ? {} : sourcifyLinkProps

const scopeToPlaygroundURL: Record<Network, Partial<Record<Layer, string>>> = {
[Network.mainnet]: {
[Layer.emerald]: `${externalLinks.dapps.abiPlayground}?network=42262&contractAddress=${address_eth}`,
[Layer.sapphire]: `${externalLinks.dapps.abiPlayground}?network=23294&contractAddress=${address_eth}`,
},
[Network.testnet]: {
[Layer.emerald]: `${externalLinks.dapps.abiPlayground}?network=42261&contractAddress=${address_eth}`,
[Layer.sapphire]: `${externalLinks.dapps.abiPlayground}?network=23295&contractAddress=${address_eth}`,
},
}
const abiPlaygroundLinkProps = {
href: scopeToPlaygroundURL[scope.network]?.[scope.layer],
rel: 'noopener noreferrer',
target: '_blank',
sx: { fontWeight: 400, color: 'inherit', textDecoration: 'underline' },
}

return (
<>
Expand All @@ -105,20 +126,41 @@ export const VerificationIcon: FC<{ address_eth: string; verified: boolean; noLi
{statusIcon[status]}
</StyledPill>
&nbsp; &nbsp;
{!noLink && (
<Typography component="span" sx={{ fontSize: '12px', color: COLORS.brandExtraDark }}>
<Trans
t={t}
i18nKey={
verified ? 'contract.verification.openInSourcify' : 'contract.verification.verifyInSourcify'
}
components={{
SourcifyLink: <Link {...linkProps} />,
}}
/>{' '}
{explainDelay && t('contract.verification.explainVerificationDelay')}
</Typography>
)}
{!noLink &&
(verified ? (
<Typography component="span" sx={{ fontSize: '12px', color: COLORS.brandExtraDark }}>
<Trans
t={t}
i18nKey={'contract.verification.openInSourcify'}
components={{
SourcifyLink: <Link {...sourcifyLinkProps} />,
}}
/>
{abiPlaygroundLinkProps.href && (
<span>
{' | '}
<Trans
t={t}
i18nKey={'contract.verification.openInAbiPlayground'}
components={{
AbiPlaygroundLink: <Link {...abiPlaygroundLinkProps} />,
}}
/>
</span>
)}
</Typography>
) : (
<Typography component="span" sx={{ fontSize: '12px', color: COLORS.brandExtraDark }}>
<Trans
t={t}
i18nKey={'contract.verification.verifyInSourcify'}
components={{
SourcifyLink: <Link {...sourcifyLinkProps} />,
}}
/>{' '}
{explainDelay && t('contract.verification.explainVerificationDelay')}
</Typography>
))}
</>
)
}
2 changes: 1 addition & 1 deletion src/app/components/Tokens/TokenDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const TokenDetails: FC<{
</dd>
<dt>{t('contract.verification.title')}</dt>
<dd>
<VerificationIcon address_eth={token.eth_contract_addr} verified={token.is_verified} />
<VerificationIcon address_eth={token.eth_contract_addr} scope={token} verified={token.is_verified} />
</dd>

<dt>{t(isMobile ? 'tokens.holders' : 'tokens.holdersCount')}</dt>
Expand Down
7 changes: 6 additions & 1 deletion src/app/components/Tokens/TokenList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ export const TokenList = (props: TokensProps) => {
width: '100%',
}}
>
<VerificationIcon address_eth={token.eth_contract_addr} verified={token.is_verified} noLink />
<VerificationIcon
address_eth={token.eth_contract_addr}
scope={token}
verified={token.is_verified}
noLink
/>
</Box>
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ export const InstanceDetailsCard: FC<InstanceDetailsCardProps> = ({
</dd>
<dt>{t('contract.verification.title')}</dt>
<dd>
<VerificationIcon address_eth={token?.eth_contract_addr!} verified={!!token?.is_verified} />
<VerificationIcon
address_eth={token?.eth_contract_addr!}
scope={token!}
verified={!!token?.is_verified}
/>
</dd>
</StyledDescriptionList>
)}
Expand Down
7 changes: 6 additions & 1 deletion src/app/pages/NFTInstanceDashboardPage/InstanceTitleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ export const InstanceTitleCard: FC<InstanceTitleCardProps> = ({ isFetched, isLoa
alignItems: 'center',
}}
>
<VerificationIcon address_eth={token.eth_contract_addr} verified={token.is_verified} noLink />
<VerificationIcon
address_eth={token.eth_contract_addr}
scope={token}
verified={token.is_verified}
noLink
/>
<AccountLink scope={scope} address={displayAddress!} alwaysTrim />
<CopyToClipboard value={displayAddress!} />
</Box>
Expand Down
6 changes: 5 additions & 1 deletion src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ export const TokenDetailsCard: FC<{ scope: SearchScope; address: string; searchT

<dt>{t('contract.verification.title')}</dt>
<dd>
<VerificationIcon address_eth={token.eth_contract_addr} verified={token.is_verified} />
<VerificationIcon
address_eth={token.eth_contract_addr}
scope={token}
verified={token.is_verified}
/>
</dd>

<dt>{t('common.type')} </dt>
Expand Down
7 changes: 6 additions & 1 deletion src/app/pages/TokenDashboardPage/TokenTitleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ export const TokenTitleCard: FC<{ scope: SearchScope; address: string; searchTer
<>
{token && (
<>
<VerificationIcon address_eth={token.eth_contract_addr} verified={token.is_verified} noLink />
<VerificationIcon
address_eth={token.eth_contract_addr}
scope={token}
verified={token.is_verified}
noLink
/>
<AccountLink
scope={token}
address={token.eth_contract_addr || token.contract_addr}
Expand Down
2 changes: 2 additions & 0 deletions src/app/utils/externalLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export const faucets = {

export const dapps = {
wRose: 'https://wrose.oasis.io/',
sourcifyRoot: 'https://sourcify.dev/',
abiPlayground: 'https://abi-playground.oasis.io/',
}

export const api = {
Expand Down
1 change: 1 addition & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
"title": "Verification",
"isVerified": "Verified",
"isNotVerified": "Unverified",
"openInAbiPlayground": "Interact in <AbiPlaygroundLink>ABI Playground</AbiPlaygroundLink>",
"openInSourcify": "Open in <SourcifyLink>Sourcify</SourcifyLink>",
"verifyInSourcify": "Verify through <SourcifyLink>Sourcify</SourcifyLink>",
"explainVerificationDelay": "If you have just verified a contract, it should take a few minutes to update here."
Expand Down

0 comments on commit ff75d5b

Please sign in to comment.