Skip to content
This repository has been archived by the owner on Jun 19, 2024. It is now read-only.

Commit

Permalink
feat: nfd domains support (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
aorumbayev authored Dec 21, 2022
1 parent 8179e4e commit fe2000e
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 11 deletions.
2 changes: 2 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const nextConfig = {
'dweb.link',
'cloudflare-ipfs.com',
'ipfs-gateway.cloud',
'*.nf.domains',
'images.nf.domains',

'images.unsplash.com',
'vitals.vercel-insights.com',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "algoworld-swapper",
"description": "Free and trustless ASA swapper, powered by Algorand ⚡️",
"version": "0.9.0",
"version": "0.9.1",
"private": true,
"author": "AlgoWorld <[email protected]>",
"license": "GPL-3.0",
Expand Down
57 changes: 47 additions & 10 deletions src/components/Headers/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import Menu from '@mui/material/Menu';
import Container from '@mui/material/Container';
import AccountBalanceWalletOutlined from '@mui/icons-material/AccountBalanceWalletOutlined';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import MenuItem from '@mui/material/MenuItem';
Expand Down Expand Up @@ -78,6 +77,8 @@ import {
import { IpfsGateway } from '@/models/Gateway';
import ValueSelect from '../Select/ValueSelect';
import { useWallet } from '@txnlab/use-wallet';
import { useAsync } from 'react-use';
import getNFDsForAddress from '@/utils/api/accounts/getNFDsForAddress';

type PageConfiguration = {
title: string;
Expand Down Expand Up @@ -111,6 +112,7 @@ const NavBar = () => {
};

const { providers, activeAddress } = useWallet();

const activeProvider = React.useMemo(() => {
return providers?.find((p) => p.isActive);
}, [providers]);
Expand All @@ -123,6 +125,26 @@ const NavBar = () => {
chain: selectedChain,
} = useAppSelector((state) => state.application);

const nfdState = useAsync(async () => {
if (!activeAddress) {
return;
}
const nfd = await getNFDsForAddress(activeAddress, selectedChain);
return nfd;
}, [activeAddress, selectedChain]);

const nfd = React.useMemo(() => {
if (nfdState.loading || nfdState.error) {
return null;
}

return nfdState.value;
}, [nfdState.error, nfdState.loading, nfdState.value]);

const nfdAvatar = React.useMemo(() => {
return nfd?.properties?.userDefined?.avatar;
}, [nfd]);

const isWalletPopupOpen = useAppSelector(
(state) => state.application.isWalletPopupOpen,
);
Expand Down Expand Up @@ -436,15 +458,30 @@ const NavBar = () => {
onClick={handleOpenUserMenu}
sx={{ p: 0, borderRadius: 1 }}
>
<AccountBalanceWalletOutlined sx={{ pr: 0.5 }} />
<Typography variant="h6">
{`${activeAddress?.slice(
0,
4,
)}...${activeAddress?.slice(
activeAddress.length - 4,
activeAddress.length,
)} `}
{/* <AccountBalanceWalletOutlined sx={{ pr: 0.5 }} /> */}
{nfd && nfdAvatar && (
<div
style={{
borderRadius: `50%`,
overflow: `hidden`,
width: `40px`,
height: `40px`,
}}
>
<Image
src={nfdAvatar}
alt="nfd-profile"
width={40}
height={40}
placeholder="blur"
blurDataURL={nfdAvatar}
/>
</div>
)}
<Typography sx={{ pl: nfd ? 1 : 0 }} variant="h6">
{`${
nfd ? nfd.name : ellipseAddress(activeAddress, 4)
}`}
</Typography>
</IconButton>
</Tooltip>
Expand Down
60 changes: 60 additions & 0 deletions src/utils/api/accounts/getNFDsForAddress.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ChainType } from '@/models/Chain';
import axios from 'axios';
import getNFDsForAddress from './getNFDsForAddress';

jest.mock(`axios`);

describe(`getNFDsForAddress`, () => {
it(`should return the NFD for the given address on mainnet`, async () => {
const address = `tnaq9cjf54ct59bmua78iuv6gtpjtdunc78q8jebwgmxyacb`;
const chain = ChainType.MainNet;
const nfd = { name: `test-nfd` };
const response = { data: [nfd] };

(axios.get as jest.MockedFunction<typeof axios.get>).mockResolvedValue(
response,
);

const result = await getNFDsForAddress(address, chain);
expect(result).toEqual(nfd);
});

it(`should return the NFD for the given address on testnet`, async () => {
const address = `tnaq9cjf54ct59bmua78iuv6gtpjtdunc78q8jebwgmxyacb`;
const chain = ChainType.TestNet;
const nfd = { name: `test-nfd` };
const response = { data: [nfd] };

(axios.get as jest.MockedFunction<typeof axios.get>).mockResolvedValue(
response,
);

const result = await getNFDsForAddress(address, chain);
expect(result).toEqual(nfd);
});

it(`should return null if the NFD is not found`, async () => {
const address = `tnaq9cjf54ct59bmua78iuv6gtpjtdunc78q8jebwgmxyacb`;
const chain = ChainType.MainNet;
const response = { data: [] };

(axios.get as jest.MockedFunction<typeof axios.get>).mockResolvedValue(
response,
);

const result = await getNFDsForAddress(address, chain);
expect(result).toBeNull();
});

it(`should return null if the request fails`, async () => {
const address = `tnaq9cjf54ct59bmua78iuv6gtpjtdunc78q8jebwgmxyacb`;
const chain = ChainType.MainNet;

(axios.get as jest.MockedFunction<typeof axios.get>).mockRejectedValue(
new Error(`Request failed`),
);

const result = await getNFDsForAddress(address, chain);
expect(result).toBeNull();
});
});
24 changes: 24 additions & 0 deletions src/utils/api/accounts/getNFDsForAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ChainType } from '@/models/Chain';
import axios from 'axios';

const NFD_MAINNET = `https://api.nf.domains`;
const NFD_TESTNET = `https://api.testnet.nf.domains`;

const getNFDsForAddress = async (address: string, chain: ChainType) => {
try {
const url = `${
chain === ChainType.MainNet ? NFD_MAINNET : NFD_TESTNET
}/nfd`;
const response = await axios.get(url, {
params: {
owner: address,
},
});
return response.data.length > 0 ? response.data[0] : null;
} catch (error) {
// handle error
return null;
}
};

export default getNFDsForAddress;

1 comment on commit fe2000e

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for algoworld-swapper ready!

✅ Preview
https://algoworld-swapper-cht2zuu1k-algoworldexplorer.vercel.app

Built with commit fe2000e.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.