Skip to content
This repository was archived by the owner on Feb 2, 2024. It is now read-only.

Commit

Permalink
feat(batch-graph): add link to etherscan to nodes (#507)
Browse files Browse the repository at this point in the history
* feat: add address and href fields to Account

* refactor: move getExplorerUrl to src/utils

* feat: add address to Account instances

* feat:add href to account instances

* feat: add href to node data

* feat: change node label color on hover

* feat: open node href on click

* feat: reduce edge distance and make label auto rotate

* fix: account.address is optional and can be undefined

* feat: add node border on hover

* fix: 🐛 add cursor pointer to graph (#509)

* fix: 🐛 add cursor pointer to graph

* fix: 🐛 rerender issue

* fix: 🐛 missing hover states

* fix: add invisible border to all nodes to avoid flickering on hover

---------

Co-authored-by: Tukan van der Borgh <[email protected]>
  • Loading branch information
alfetopito and tukantje authored Jun 5, 2023
1 parent bbccc41 commit 9b2b2b8
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 37 deletions.
3 changes: 3 additions & 0 deletions src/api/tenderly/tenderlyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export function accountAddressesInvolved(
if (transferAddresses.has(contract.address))
result.set(contract.address, {
alias: _contractName(contract.contract_name),
address: contract.address,
})
})
trades.forEach((trade) => {
Expand All @@ -155,6 +156,7 @@ export function accountAddressesInvolved(
if (!result.has(trade.owner)) {
result.set(trade.owner, {
alias: ALIAS_TRADER_NAME,
address: trade.owner,
})
}
})
Expand All @@ -167,6 +169,7 @@ export function accountAddressesInvolved(
if (!result.get(address)) {
result.set(address, {
alias: abbreviateString(address, 6, 4),
address,
})
}
})
Expand Down
2 changes: 2 additions & 0 deletions src/api/tenderly/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export interface Transfer {

export interface Account {
alias: string
address?: string
href?: string
}

export interface Contract {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default class ElementsBuilder {
label: !hideLabel ? node.entity.alias : '',
type: node.type,
parent: parent ? `${TypeNodeOnTx.NetworkNode}:${parent}` : undefined,
href: node.entity.href,
},
}
}
Expand Down
17 changes: 17 additions & 0 deletions src/apps/explorer/components/TransanctionBatchGraph/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,31 @@ export function useCytoscape(params: UseCytoscapeParams): UseCytoscapeReturn {
})
cy.on('mouseover', 'edge', (event): void => {
event.target.addClass('hover')
document.getElementById('tx-graph')?.classList.add('hover')
})
cy.on('mouseout', 'edge', (event): void => {
event.target.removeClass('hover')
document.getElementById('tx-graph')?.classList.remove('hover')
})
cy.on('mouseover', 'node', (event): void => {
if (event.target.data('href')) {
event.target.addClass('hover')
document.getElementById('tx-graph')?.classList.add('hover')
}
})
cy.on('mouseout', 'node', (event): void => {
event.target.removeClass('hover')
document.getElementById('tx-graph')?.classList.remove('hover')
})
cy.on('tap', 'node', (event): void => {
const href = event.target.data('href')
href && window.open(href, '_blank')
})
cy.nodes().noOverlap({ padding: 5 })

return (): void => {
cy.removeAllListeners()
document.getElementById('tx-graph')?.classList.remove('hover')
removePopper(cyPopperRef)
}
}, [cytoscapeRef, elements.length])
Expand Down
4 changes: 2 additions & 2 deletions src/apps/explorer/components/TransanctionBatchGraph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function TransactionBatchGraph(params: GraphBatchTxParams): JSX.Element {
}

return (
<>
<div id="tx-graph" style={{ flex: 1 }}>
<WrapperCytoscape
elements={elements}
layout={layout}
Expand Down Expand Up @@ -139,6 +139,6 @@ export function TransactionBatchGraph(params: GraphBatchTxParams): JSX.Element {
/>
</LayoutButton>
</FloatingWrapper>
</>
</div>
)
}
27 changes: 25 additions & 2 deletions src/apps/explorer/components/TransanctionBatchGraph/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,29 @@ export function STYLESHEET(theme: DefaultTheme): Stylesheet[] {
'background-color': theme.bg2,
},
},

{
selector: 'node[label].hover',
style: {
color: theme.orange,
},
},
{
selector: 'node',
style: {
'border-style': 'solid',
'border-width': 3,
'border-opacity': 0,
},
},
{
selector: 'node.hover',
style: {
'border-color': theme.orange,
'border-style': 'solid',
'border-width': 3,
'border-opacity': 0.75,
},
},
{
selector: 'edge[label]',
style: {
Expand All @@ -113,6 +135,7 @@ export function STYLESHEET(theme: DefaultTheme): Stylesheet[] {
'text-background-shape': 'roundrectangle',
'font-size': '16px',
'min-zoomed-font-size': 8,
'text-rotation': 'autorotate',
},
},
{
Expand All @@ -121,7 +144,6 @@ export function STYLESHEET(theme: DefaultTheme): Stylesheet[] {
'curve-style': 'bezier',
'font-size': '15px',
'text-background-padding': '3px',
'control-point-step-size': 75,
},
},
{
Expand Down Expand Up @@ -180,6 +202,7 @@ export function STYLESHEET(theme: DefaultTheme): Stylesheet[] {
style: {
'border-style': 'dashed',
'border-opacity': 0.8,
'border-width': 1,
opacity: 0.8,
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/apps/explorer/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export const GlobalStyle = createGlobalStyle`
${ScrollBarStyle}
}
.hover {
cursor: pointer;
}
/* Cystoscape - BatchViewer styles */
.target-popper {
max-width: 50rem;
Expand Down
34 changes: 1 addition & 33 deletions src/components/common/BlockExplorerLink/BlockExplorerLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { ExternalLink } from 'components/analytics/ExternalLink'
import LogoWrapper, { LOGO_MAP } from 'components/common/LogoWrapper'

import { abbreviateString } from 'utils'

type BlockExplorerLinkType = 'tx' | 'address' | 'contract' | 'token' | 'event'
import { BlockExplorerLinkType, getExplorerUrl } from 'utils/getExplorerUrl'

export interface Props {
/**
Expand Down Expand Up @@ -40,37 +39,6 @@ export interface Props {
showLogo?: boolean
}

function getEtherscanUrlPrefix(networkId: Network): string {
return !networkId || networkId === Network.MAINNET || networkId === Network.GNOSIS_CHAIN
? ''
: (Network[networkId] || '').toLowerCase() + '.'
}

function getEtherscanUrlSuffix(type: BlockExplorerLinkType, identifier: string): string {
switch (type) {
case 'tx':
return `tx/${identifier}`
case 'event':
return `tx/${identifier}#eventlog`
case 'address':
return `address/${identifier}`
case 'contract':
return `address/${identifier}#code`
case 'token':
return `token/${identifier}`
}
}

function getEtherscanUrl(host: string, networkId: number, type: BlockExplorerLinkType, identifier: string): string {
return `https://${getEtherscanUrlPrefix(networkId)}${host}/${getEtherscanUrlSuffix(type, identifier)}`
}

function getExplorerUrl(networkId: number, type: BlockExplorerLinkType, identifier: string): string {
return networkId === Network.GNOSIS_CHAIN
? getEtherscanUrl('gnosisscan.io', networkId, type, identifier)
: getEtherscanUrl('etherscan.io', networkId, type, identifier)
}

/**
* Dumb BlockExplorerLink, a pure UI component
*
Expand Down
5 changes: 5 additions & 0 deletions src/hooks/useTxBatchTrades.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { SingleErc20State } from 'state/erc20'
import { Order } from 'api/operator'
import BigNumber from 'bignumber.js'
import { usePrevious } from './usePrevious'
import { getExplorerUrl } from 'utils/getExplorerUrl'

interface TxBatchTrades {
trades: Trade[]
Expand Down Expand Up @@ -104,13 +105,17 @@ export function useTxBatchTrades(
if (!(order.receiver in _accounts)) {
accountsWithReceiver[order.receiver] = {
alias: ALIAS_TRADER_NAME,
address: order.receiver,
}
}
accountsWithReceiver[order.receiver] = {
...accountsWithReceiver[order.receiver],
owner: order.owner,
}
})
Object.values(accountsWithReceiver).forEach((account) => {
if (account.address) account.href = getExplorerUrl(network, 'address', account.address)
})

setErc20Addresses(transfersWithKind.map((transfer: Transfer): string => transfer.token))
setTxBatchTrades({ trades, transfers: transfersWithKind })
Expand Down
34 changes: 34 additions & 0 deletions src/utils/getExplorerUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Network } from 'types'

export type BlockExplorerLinkType = 'tx' | 'address' | 'contract' | 'token' | 'event'

function getEtherscanUrlPrefix(networkId: Network): string {
return !networkId || networkId === Network.MAINNET || networkId === Network.GNOSIS_CHAIN
? ''
: (Network[networkId] || '').toLowerCase() + '.'
}

function getEtherscanUrlSuffix(type: BlockExplorerLinkType, identifier: string): string {
switch (type) {
case 'tx':
return `tx/${identifier}`
case 'event':
return `tx/${identifier}#eventlog`
case 'address':
return `address/${identifier}`
case 'contract':
return `address/${identifier}#code`
case 'token':
return `token/${identifier}`
}
}

function getEtherscanUrl(host: string, networkId: number, type: BlockExplorerLinkType, identifier: string): string {
return `https://${getEtherscanUrlPrefix(networkId)}${host}/${getEtherscanUrlSuffix(type, identifier)}`
}

export function getExplorerUrl(networkId: number, type: BlockExplorerLinkType, identifier: string): string {
return networkId === Network.GNOSIS_CHAIN
? getEtherscanUrl('gnosisscan.io', networkId, type, identifier)
: getEtherscanUrl('etherscan.io', networkId, type, identifier)
}

0 comments on commit 9b2b2b8

Please sign in to comment.