Skip to content

Commit

Permalink
feat: add ethereum address mapping (#3015)
Browse files Browse the repository at this point in the history
  • Loading branch information
Melisa Anabella Rossi committed Jan 19, 2024
1 parent 2633d00 commit e818c80
Show file tree
Hide file tree
Showing 42 changed files with 2,225 additions and 156 deletions.
600 changes: 515 additions & 85 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"@types/uuid": "^3.4.4",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"canvas": "^2.11.2",
"concurrently": "^7.2.2",
"decentraland-rpc": "^3.1.8",
"eslint": "^7.28.0",
Expand Down
31 changes: 31 additions & 0 deletions src/components/ENSDetailPage/ENSDetailPage.container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { connect } from 'react-redux'
import { Dispatch } from 'redux'
import { push } from 'connected-react-router'
import { getENSBySubdomain, getLoading } from 'modules/ens/selectors'
import { RootState } from 'modules/common/types'
import { getENSName } from 'modules/location/selectors'
import { openModal } from 'modules/modal/actions'
import { MapStateProps, MapDispatchProps } from './ENSDetailPage.types'
import ENSDetailPage from './ENSDetailPage'
import { isLoadingType } from 'decentraland-dapps/dist/modules/loading/selectors'
import { FETCH_ENS_REQUEST, fetchENSRequest } from 'modules/ens/actions'
import { getAvatar, getName } from 'modules/profile/selectors'

const mapState = (state: RootState): MapStateProps => {
const name = getENSName(state)
return {
name,
ens: name ? getENSBySubdomain(state, `${name}.dcl.eth`) : null,
isLoading: isLoadingType(getLoading(state), FETCH_ENS_REQUEST),
alias: getName(state),
avatar: getAvatar(state)
}
}

const mapDispatch = (dispatch: Dispatch): MapDispatchProps => ({
onFetchENS: (name: string) => dispatch(fetchENSRequest(name)),
onOpenModal: (name, metadata) => dispatch(openModal(name, metadata)),
onNavigate: path => dispatch(push(path))
})

export default connect(mapState, mapDispatch)(ENSDetailPage)
112 changes: 112 additions & 0 deletions src/components/ENSDetailPage/ENSDetailPage.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.main {
display: flex;
padding: 35px;
background: var(--secondary);
border-radius: 10px;
gap: 50px;
}

.fields {
display: flex;
flex-direction: column;
flex: 1;
gap: 20px;
}

.ensImage {
width: 326px;
height: 326px;
border-radius: 10px;
}

.field {
display: flex;
flex-direction: column;
flex: 1;
gap: 24px;
}

.fieldContainer {
display: flex;
}

.fieldContainer:first-child {
border-bottom: 1px solid var(--secondary-text);
padding: 40px 0 20px 0;
}

.fieldTitle {
font-size: 14px;
color: var(--secondary-text);
}

.subdomain {
display: flex;
font-weight: bold;
font-size: 40px;
line-height: 40px;
color: var(--secondary-text);
align-items: center;
gap: 10px;
}

.subdomain span span {
color: white;
}

.unassign {
border-radius: 8px;
background: #302c36;
color: white;
font-size: 16px;
padding: 0 20px;
height: 34px;
display: flex;
align-items: center;
justify-content: center;
width: fit-content;
}

.actionBtn {
width: fit-content;
min-width: none;
}

.avatar {
display: flex;
align-items: center;
gap: 8px;
color: var(--secondary-text);
}

.avatarImg {
width: 30px;
height: 30px;
border-radius: 50%;
background: #43404a;
}

.avatarName {
color: white;
font-weight: bold;
}

.ensBtn:global(.ui.button) {
background: #302c36;
color: white;
width: fit-content;
min-width: none;
}

.address {
display: flex;
align-items: center;
gap: 10px;
}

.returnLink:global(.ui.button) {
color: var(--secondary-text) !important;
font-size: 20px;
margin-bottom: 30px;
text-transform: none;
}
154 changes: 154 additions & 0 deletions src/components/ENSDetailPage/ENSDetailPage.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { ENS } from 'modules/ens/types'
import { renderWithProviders } from 'specs/utils'
import ENSDetailPage from './ENSDetailPage'
import { Props } from './ENSDetailPage.types'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { getCroppedAddress } from 'components/ENSListPage/utils'

jest.mock('components/LoggedInDetailPage', () => ({ children }: any) => <div>{children}</div>)
function renderENSDetailPage(props: Partial<Props>) {
return renderWithProviders(
<ENSDetailPage
name="test"
ens={null}
alias="test"
avatar={null}
isLoading={false}
onOpenModal={jest.fn()}
onFetchENS={jest.fn()}
onNavigate={jest.fn()}
{...props}
/>
)
}

const ensSample: ENS = {
name: 'test',
subdomain: 'test',
content: '',
ensOwnerAddress: '0xtest2',
nftOwnerAddress: '0xtest1',
resolver: '0xtest3',
tokenId: '',
ensAddressRecord: ''
}

describe('when ens is defined', () => {
let ens: ENS

describe('and the name is the same as the alias', () => {
let alias: string
beforeEach(() => {
ens = {
...ensSample,
name: 'test'
}
alias = 'test'
})

it('should show alias info', () => {
const screen = renderENSDetailPage({ ens, alias })
expect(screen.getByTestId('alias-avatar')).toBeInTheDocument()
})
})

describe('and the name is not the same as the alias', () => {
let alias: string
beforeEach(() => {
ens = {
...ensSample,
name: 'test'
}
alias = 'test2'
})

it('should not show alias info', () => {
const screen = renderENSDetailPage({ ens, alias })
expect(screen.queryByTestId('alias-avatar')).not.toBeInTheDocument()
})

it('should show assigned as alias button', () => {
const screen = renderENSDetailPage({ ens, alias })
expect(screen.getByRole('button', { name: t('ens_detail_page.set_as_primary') })).toBeInTheDocument()
})
})

describe('and there is already an address assigned to the ens', () => {
let address: string
beforeEach(() => {
address = '0xA4f689625F6F51AdF691a64D38772BE85090test'
ens = {
...ensSample,
ensAddressRecord: address
}
})

it('should show cropped address info', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByText(getCroppedAddress(address))).toBeInTheDocument()
})

it('should show edit address button', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByRole('button', { name: t('ens_detail_page.edit_address') })).toBeInTheDocument()
})
})

describe('and there is no address assigned to the ens', () => {
beforeEach(() => {
ens = {
...ensSample,
ensAddressRecord: ''
}
})

it('should show add address button', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByRole('button', { name: t('ens_list_page.button.link_to_address') })).toBeInTheDocument()
})
})

describe('and the name has a linked land', () => {
describe('and the land is a coord', () => {
beforeEach(() => {
ens = {
...ensSample,
landId: '4,4'
}
})
it('should show land field info', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByTestId('land-field')).toBeInTheDocument()
})
})

describe('and the land is an estate', () => {
describe('and the land is a coord', () => {
beforeEach(() => {
ens = {
...ensSample,
landId: '4'
}
})
it('should estate field button', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByTestId('estate-field')).toBeInTheDocument()
})
})
})
})

describe('and the ens does not have a linked land', () => {
beforeEach(() => {
ens = {
...ensSample,
landId: ''
}
})

it('should show add address button', () => {
const screen = renderENSDetailPage({ ens })
expect(screen.getByRole('button', { name: t('ens_list_page.button.assign_to_land') })).toBeInTheDocument()
})
})
})
Loading

0 comments on commit e818c80

Please sign in to comment.