Skip to content

Commit

Permalink
feat: recognize ens domains (#351)
Browse files Browse the repository at this point in the history
* feat: recognize ens domains

* refactor: added ens recognition and more tests

* fix: validation mechanism to accept ENS and CIDs

* feat: support non-ascii characters for ENS

* fix: asset summary component to support ENS issue
  • Loading branch information
vojtechsimetka committed May 31, 2022
1 parent b6f138b commit 5917a13
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 50 deletions.
64 changes: 36 additions & 28 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"url": "https://github.com/ethersphere/bee-dashboard.git"
},
"dependencies": {
"@ethersphere/bee-js": "^3.3.4",
"@ethersphere/bee-js": "^4.1.1",
"@ethersphere/manifest-js": "1.1.0",
"@ethersphere/swarm-cid": "^0.1.0",
"@material-ui/core": "4.12.3",
Expand Down
19 changes: 13 additions & 6 deletions src/pages/files/AssetSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import * as swarmCid from '@ethersphere/swarm-cid'
import { Box } from '@material-ui/core'
import { ReactElement } from 'react'
import { Utils } from '@ethersphere/bee-js'
import { DocumentationText } from '../../components/DocumentationText'
import ExpandableListItemKey from '../../components/ExpandableListItemKey'
import ExpandableListItemLink from '../../components/ExpandableListItemLink'

interface Props {
isWebsite?: boolean
hash: string
reference: string
}

export function AssetSummary({ isWebsite, hash }: Props): ReactElement {
export function AssetSummary({ isWebsite, reference }: Props): ReactElement {
const isHash = Utils.isHexString(reference) && reference.length === 64

return (
<>
<Box mb={4}>
<ExpandableListItemKey label="Swarm hash" value={hash} />
<ExpandableListItemLink label="Share on Swarm Gateway" value={`https://gateway.ethswarm.org/access/${hash}`} />
{isWebsite && (
{isHash && <ExpandableListItemKey label="Swarm hash" value={reference} />}
{!isHash && <ExpandableListItemLink label="ENS" value={reference} />}
<ExpandableListItemLink
label="Share on Swarm Gateway"
value={`https://gateway.ethswarm.org/access/${reference}`}
/>
{isWebsite && isHash && (
<ExpandableListItemLink
label="BZZ Link"
value={`https://${swarmCid.encodeManifestReference(hash).toString()}.bzz.link`}
value={`https://${swarmCid.encodeManifestReference(reference).toString()}.bzz.link`}
/>
)}
</Box>
Expand Down
15 changes: 11 additions & 4 deletions src/pages/files/Download.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { History } from '../../components/History'
import { Context, defaultUploadOrigin } from '../../providers/File'
import { Context as SettingsContext } from '../../providers/Settings'
import { ROUTES } from '../../routes'
import { recognizeSwarmHash } from '../../utils'
import { recognizeEnsOrSwarmHash, regexpEns } from '../../utils'
import { determineHistoryName, HISTORY_KEYS, putHistory } from '../../utils/local-storage'
import { FileNavigation } from './FileNavigation'

Expand All @@ -23,10 +23,17 @@ export function Download(): ReactElement {
const navigate = useNavigate()

const validateChange = (value: string) => {
if (Utils.isHexString(value, 64) || Utils.isHexString(value, 128) || !value.trim().length) {
if (
Utils.isHexString(value, 64) ||
Utils.isHexString(value, 128) ||
!value.trim().length ||
regexpEns.test(value)
) {
setReferenceError(undefined)
} else {
setReferenceError('Incorrect format of swarm hash. Expected 64 or 128 hexstring characters.')
setReferenceError(
'Incorrect format of swarm hash. Expected 64 or 128 hexstring characters, bzz.link url or ENS domain.',
)
}
}

Expand Down Expand Up @@ -83,7 +90,7 @@ export function Download(): ReactElement {
confirmLabelDisabled={Boolean(referenceError) || loading}
placeholder="e.g. 31fb0362b1a42536134c86bc58b97ac0244e5c6630beec3e27c2d1cecb38c605"
expandedOnly
mapperFn={value => recognizeSwarmHash(value)}
mapperFn={value => recognizeEnsOrSwarmHash(value)}
loading={loading}
/>
<History title="Download History" localStorageKey={HISTORY_KEYS.DOWNLOAD_HISTORY} />
Expand Down
2 changes: 1 addition & 1 deletion src/pages/files/Share.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export function Share(): ReactElement {
<AssetPreview metadata={metadata} previewUri={preview} />
</Box>
<Box mb={4}>
<AssetSummary isWebsite={metadata?.isWebsite} hash={reference} />
<AssetSummary isWebsite={metadata?.isWebsite} reference={reference} />
</Box>
<DownloadActionBar
onOpen={onOpen}
Expand Down
64 changes: 56 additions & 8 deletions src/utils/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { extractSwarmHash, extractSwarmCid, recognizeSwarmHash } from './index'
import { extractSwarmHash, extractSwarmCid, extractEns, recognizeEnsOrSwarmHash } from './index'

interface TestObject {
input: string
Expand Down Expand Up @@ -122,16 +122,64 @@ describe('extractSwarmCid', () => {
})
})

describe('recognizeSwarmHash', () => {
test('should correctly extract hash', () => {
;[...correctHashes, ...correctCids].forEach(({ input, expectedOutput }) => {
const hash = recognizeSwarmHash(input)
const correctEns: TestObject[] = [
{
input: 'test.eth',
expectedOutput: 'test.eth',
},
{
input: 't-est.eth',
expectedOutput: 't-est.eth',
},
{
input: 'http://test.eth/whatever',
expectedOutput: 'test.eth',
},
{
input: 'https://alice.test.eth?whatever',
expectedOutput: 'alice.test.eth',
},
{
input: 'swarm.example.eth/?id=1&page=2',
expectedOutput: 'swarm.example.eth',
},
{
input: 'http://swarm.example.eth#up',
expectedOutput: 'swarm.example.eth',
},
{
input: 'http://site.eth:8008',
expectedOutput: 'site.eth',
},
]

const wrongEns: string[] = ['http://test.ethereum/whatever']

describe('extractEns', () => {
test('should correctly extract ens domain', () => {
correctEns.forEach(({ input, expectedOutput }) => {
const hash = extractEns(input)
expect(hash).toBe(expectedOutput)
})
})
test('should not extract ens from incorrect inputs', () => {
wrongEns.forEach(url => {
const hash = extractEns(url)
expect(hash).toBe(undefined)
})
})
})

describe('recognizeEnsOrSwarmHash', () => {
test('should correctly extract hash or ens', () => {
;[...correctHashes, ...correctCids, ...correctEns].forEach(({ input, expectedOutput }) => {
const hash = recognizeEnsOrSwarmHash(input)
expect(hash).toBe(expectedOutput)
})
})
test('should not extract hash from incorrect inputs but instead return them', () => {
;[...wrongHashes, ...wrongCids].forEach(url => {
const hash = recognizeSwarmHash(url)
test('should not extract hash or ens from incorrect inputs but instead return them', () => {
;[...wrongHashes, ...wrongCids, ...wrongEns].forEach(url => {
const hash = recognizeEnsOrSwarmHash(url)
expect(hash).toBe(url)
})
})
Expand Down
14 changes: 12 additions & 2 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,18 @@ export function extractSwarmCid(s: string): string | undefined {
}
}

export function recognizeSwarmHash(value: string): string {
return extractSwarmHash(value) || extractSwarmCid(value) || value
// Matches any number of subdomain with .eth
// e.g. this.is.just-a-test.eth
export const regexpEns = /((?:(?:[^-./?:\s][^./?:\s]{0,61}[^-./?:\s]|[^-./?:\s]{1,2})\.)+eth)(?:$|[/?:#].*)/i

export function extractEns(value: string): string | undefined {
const matches = value.match(regexpEns)

return (matches && matches[1]) || undefined
}

export function recognizeEnsOrSwarmHash(value: string): string {
return extractEns(value) || extractSwarmHash(value) || extractSwarmCid(value) || value
}

export function uuidV4(): string {
Expand Down

0 comments on commit 5917a13

Please sign in to comment.