Skip to content

Commit 8b5f6e7

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent 8784bb0 commit 8b5f6e7

27 files changed

+2865
-88
lines changed

packages/hardhat/deployments/baseSepolia/ENSSubnameRegistrar.json

Lines changed: 30 additions & 24 deletions
Large diffs are not rendered by default.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"language": "Solidity",
3+
"sources": {
4+
"contracts/ENSSubnameRegistrar.sol": {
5+
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n// Import Durin’s registry interface\ninterface IL2Registry {\n /// Called to create a subnode under parentNode.\n /// Returns the ENS namehash of the new node.\n function createSubnode(\n bytes32 node,\n string calldata label,\n address owner,\n bytes[] calldata data\n ) external returns (bytes32);\n function baseNode() external view returns (bytes32);\n function setAddr(bytes32 node, uint256 coinType, bytes calldata a) external;\n function makeNode(\n bytes32 parentNode,\n string calldata label\n ) external pure returns (bytes32);\n function ownerOf(uint256 tokenId) external view returns (address owner);\n function namehash(string calldata name) external pure returns (bytes32);\n \n}\n\n\ncontract ENSSubnameRegistrar{\n IL2Registry public registry;\n\n // Track creator info per creatorNode\n mapping(bytes32 => address) public creatorOwner;\n mapping(address => bytes32[]) public creatorFans;\n\n event CreatorRegistered(bytes32 indexed creatorNode, string label, address indexed owner);\n event FanRegistered(bytes32 indexed fanNode, string label, string creatorLabel, address indexed owner);\n\n /// @notice The chainId for the current chain\n uint256 public chainId;\n\n /// @notice The coinType for the current chain (ENSIP-11)\n uint256 public immutable coinType;\n\n /// @notice Initializes the registrar with a registry contract\n /// @param _registry Address of the L2Registry contract\n constructor(address _registry) {\n // Save the chainId in memory (can only access this in assembly)\n assembly {\n sstore(chainId.slot, chainid())\n }\n\n // Calculate the coinType for the current chain according to ENSIP-11\n coinType = (0x80000000 | chainId) >> 0;\n\n // Save the registry address\n registry = IL2Registry(_registry);\n }\n\n /// Admin registers a creator subname under the root (e.g. `davido.fantoken.eth`)\n function registerCreator(\n string calldata label,\n address creatorAddr\n ) external returns (bytes32 creatorNode) {\n\n bytes32 node = _labelToNode(label);\n require(creatorOwner[node] == address(0), \"Label taken\");\n bytes memory addr = abi.encodePacked(creatorAddr); // Convert address to bytes\n\n // Set the forward address for the current chain. This is needed for reverse resolution.\n // E.g. if this contract is deployed to Base, set an address for chainId 8453 which is\n // coinType 2147492101 according to ENSIP-11.\n registry.setAddr(node, coinType, addr);\n\n // Set the forward address for mainnet ETH (coinType 60) for easier debugging.\n registry.setAddr(node, 60, addr);\n\n creatorNode = registry.createSubnode(\n registry.baseNode(),\n label,\n creatorAddr,\n new bytes[](0)\n );\n\n creatorOwner[creatorNode] = creatorAddr;\n emit CreatorRegistered(creatorNode, label, creatorAddr);\n }\n\n /// Fan registers their subname under creator, but ONLY if they follow that creator via EFP\n function registerFan(\n string calldata creatorLabel,\n string calldata label\n ) external returns (bytes32 fanNode) {\n bytes32 creatorNode = registry.namehash(creatorLabel);\n address creatorAddr = creatorOwner[creatorNode];\n require(creatorAddr != address(0), \"Unknown creator\");\n\n fanNode = registry.createSubnode(\n creatorNode,\n label,\n msg.sender,\n new bytes[](0)\n );\n\n bytes memory fanAddrBytes = abi.encodePacked(msg.sender);\n registry.setAddr(fanNode, coinType, fanAddrBytes); // chain-specific coinType\n registry.setAddr(fanNode, 60, fanAddrBytes); // 60 = ETH for convenience/debug\n\n creatorFans[creatorAddr].push(fanNode);\n emit FanRegistered(fanNode, label, creatorLabel, msg.sender);\n }\n\n function _labelToNode(\n string calldata label\n ) private view returns (bytes32) {\n return registry.makeNode(registry.baseNode(), label);\n }\n}\n"
6+
}
7+
},
8+
"settings": {
9+
"optimizer": {
10+
"enabled": true,
11+
"runs": 200
12+
},
13+
"evmVersion": "paris",
14+
"outputSelection": {
15+
"*": {
16+
"*": [
17+
"abi",
18+
"evm.bytecode",
19+
"evm.deployedBytecode",
20+
"evm.methodIdentifiers",
21+
"metadata",
22+
"devdoc",
23+
"userdoc",
24+
"storageLayout",
25+
"evm.gasEstimates"
26+
],
27+
"": [
28+
"ast"
29+
]
30+
}
31+
},
32+
"metadata": {
33+
"useLiteralContent": true
34+
}
35+
}
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"language": "Solidity",
3+
"sources": {
4+
"contracts/ENSSubnameRegistrar.sol": {
5+
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n// Import Durin’s registry interface\ninterface IL2Registry {\n /// Called to create a subnode under parentNode.\n /// Returns the ENS namehash of the new node.\n function createSubnode(\n bytes32 node,\n string calldata label,\n address owner,\n bytes[] calldata data\n ) external returns (bytes32);\n function baseNode() external view returns (bytes32);\n function setAddr(bytes32 node, uint256 coinType, bytes calldata a) external;\n function makeNode(\n bytes32 parentNode,\n string calldata label\n ) external pure returns (bytes32);\n function ownerOf(uint256 tokenId) external view returns (address owner);\n function namehash(string calldata name) external pure returns (bytes32);\n \n}\n\n\ncontract ENSSubnameRegistrar{\n IL2Registry public registry;\n\n // Track creator info per creatorNode\n mapping(bytes32 => address) public creatorOwner;\n mapping(address => bytes32[]) public creatorFans;\n\n event CreatorRegistered(bytes32 indexed creatorNode, string label, address indexed owner);\n event FanRegistered(bytes32 indexed fanNode, string label, address indexed owner);\n\n /// @notice The chainId for the current chain\n uint256 public chainId;\n\n /// @notice The coinType for the current chain (ENSIP-11)\n uint256 public immutable coinType;\n\n /// @notice Initializes the registrar with a registry contract\n /// @param _registry Address of the L2Registry contract\n constructor(address _registry) {\n // Save the chainId in memory (can only access this in assembly)\n assembly {\n sstore(chainId.slot, chainid())\n }\n\n // Calculate the coinType for the current chain according to ENSIP-11\n coinType = (0x80000000 | chainId) >> 0;\n\n // Save the registry address\n registry = IL2Registry(_registry);\n }\n\n /// Admin registers a creator subname under the root (e.g. `davido.fantoken.eth`)\n function registerCreator(\n string calldata label,\n address creatorAddr\n ) external returns (bytes32 creatorNode) {\n\n bytes32 node = _labelToNode(label);\n require(creatorOwner[node] == address(0), \"Label taken\");\n bytes memory addr = abi.encodePacked(creatorAddr); // Convert address to bytes\n\n // Set the forward address for the current chain. This is needed for reverse resolution.\n // E.g. if this contract is deployed to Base, set an address for chainId 8453 which is\n // coinType 2147492101 according to ENSIP-11.\n registry.setAddr(node, coinType, addr);\n\n // Set the forward address for mainnet ETH (coinType 60) for easier debugging.\n registry.setAddr(node, 60, addr);\n\n creatorNode = registry.createSubnode(\n registry.baseNode(),\n label,\n creatorAddr,\n new bytes[](0)\n );\n\n creatorOwner[creatorNode] = creatorAddr;\n emit CreatorRegistered(creatorNode, label, creatorAddr);\n }\n\n /// Fan registers their subname under creator, but ONLY if they follow that creator via EFP\n function registerFan(\n string calldata creatorLabel,\n string calldata label\n ) external returns (bytes32 fanNode) {\n bytes32 creatorNode = registry.namehash(creatorLabel);\n address creatorAddr = creatorOwner[creatorNode];\n require(creatorAddr != address(0), \"Unknown creator\");\n\n fanNode = registry.createSubnode(\n creatorNode,\n label,\n msg.sender,\n new bytes[](0)\n );\n\n bytes memory fanAddrBytes = abi.encodePacked(msg.sender);\n registry.setAddr(fanNode, coinType, fanAddrBytes); // chain-specific coinType\n registry.setAddr(fanNode, 60, fanAddrBytes); // 60 = ETH for convenience/debug\n\n creatorFans[creatorAddr].push(fanNode);\n emit FanRegistered(fanNode, label, msg.sender);\n }\n\n function _labelToNode(\n string calldata label\n ) private view returns (bytes32) {\n return registry.makeNode(registry.baseNode(), label);\n }\n}\n"
6+
}
7+
},
8+
"settings": {
9+
"optimizer": {
10+
"enabled": true,
11+
"runs": 200
12+
},
13+
"evmVersion": "paris",
14+
"outputSelection": {
15+
"*": {
16+
"*": [
17+
"abi",
18+
"evm.bytecode",
19+
"evm.deployedBytecode",
20+
"evm.methodIdentifiers",
21+
"metadata",
22+
"devdoc",
23+
"userdoc",
24+
"storageLayout",
25+
"evm.gasEstimates"
26+
],
27+
"": [
28+
"ast"
29+
]
30+
}
31+
},
32+
"metadata": {
33+
"useLiteralContent": true
34+
}
35+
}
36+
}

packages/nextjs/app/page.tsx

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,97 @@
11
"use client";
22

3-
import Link from "next/link";
43
import type { NextPage } from "next";
54
import { useAccount } from "wagmi";
6-
import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
7-
import { Address } from "~~/components/scaffold-eth";
5+
import { Creator } from "~~/components/Creator";
6+
import { CreatorProfile } from "~~/components/CreatorProfile";
7+
import { Fan } from "~~/components/Fan";
8+
import { Profile } from "~~/components/Profile";
9+
import { Subnames } from "~~/components/Subnames";
810

911
const Home: NextPage = () => {
1012
const { address: connectedAddress } = useAccount();
1113

1214
return (
13-
<>
14-
<div className="flex items-center flex-col grow pt-10">
15-
<div className="px-5">
16-
<h1 className="text-center">
17-
<span className="block text-2xl mb-2">Welcome to</span>
18-
<span className="block text-4xl font-bold">Scaffold-ETH 2</span>
15+
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800">
16+
<div className="container mx-auto px-4 py-16">
17+
{/* Header */}
18+
<div className="text-center mb-16">
19+
<h1 className="text-5xl font-bold text-gray-900 dark:text-white mb-4">
20+
<span className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">FanTag</span>
1921
</h1>
20-
<div className="flex justify-center items-center space-x-2 flex-col">
21-
<p className="my-2 font-medium">Connected Address:</p>
22-
<Address address={connectedAddress} />
23-
</div>
24-
25-
<p className="text-center text-lg">
26-
Get started by editing{" "}
27-
<code className="italic bg-base-300 text-base font-bold max-w-full break-words break-all inline-block">
28-
packages/nextjs/app/page.tsx
29-
</code>
30-
</p>
31-
<p className="text-center text-lg">
32-
Edit your smart contract{" "}
33-
<code className="italic bg-base-300 text-base font-bold max-w-full break-words break-all inline-block">
34-
YourContract.sol
35-
</code>{" "}
36-
in{" "}
37-
<code className="italic bg-base-300 text-base font-bold max-w-full break-words break-all inline-block">
38-
packages/hardhat/contracts
39-
</code>
22+
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
23+
Create and claim ENS subdomains for creators and their communities. Connect with your favorite creators
24+
through decentralized identity.
4025
</p>
4126
</div>
4227

43-
<div className="grow bg-base-300 w-full mt-16 px-8 py-12">
44-
<div className="flex justify-center items-center gap-12 flex-col md:flex-row">
45-
<div className="flex flex-col bg-base-100 px-10 py-10 text-center items-center max-w-xs rounded-3xl">
46-
<BugAntIcon className="h-8 w-8 fill-secondary" />
47-
<p>
48-
Tinker with your smart contract using the{" "}
49-
<Link href="/debug" passHref className="link">
50-
Debug Contracts
51-
</Link>{" "}
52-
tab.
53-
</p>
28+
{/* Main Content */}
29+
<div className="max-w-6xl mx-auto">
30+
{!connectedAddress ? (
31+
<div className="text-center">
32+
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8 max-w-md mx-auto">
33+
<h2 className="text-2xl font-semibold mb-4">Welcome to FanTag</h2>
34+
<p className="text-gray-600 dark:text-gray-400 mb-6">
35+
Connect your wallet to start creating and claiming ENS subdomains
36+
</p>
37+
<div className="text-sm text-gray-500 dark:text-gray-400">
38+
<p>🎯 Register as a creator</p>
39+
<p>🎪 Claim fan subdomains</p>
40+
<p>🔗 Build your Web3 identity</p>
41+
</div>
42+
</div>
5443
</div>
55-
<div className="flex flex-col bg-base-100 px-10 py-10 text-center items-center max-w-xs rounded-3xl">
56-
<MagnifyingGlassIcon className="h-8 w-8 fill-secondary" />
57-
<p>
58-
Explore your local transactions with the{" "}
59-
<Link href="/blockexplorer" passHref className="link">
60-
Block Explorer
61-
</Link>{" "}
62-
tab.
63-
</p>
44+
) : (
45+
<div className="space-y-12">
46+
{/* Full-width stacked sections */}
47+
<div className="space-y-8 w-screen max-w-3xl mx-auto">
48+
<Profile />
49+
<Subnames />
50+
<CreatorProfile />
51+
</div>
52+
53+
{/* Actions Section */}
54+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
55+
<div className="flex justify-center">
56+
<Creator />
57+
</div>
58+
<div className="flex justify-center">
59+
<Fan />
60+
</div>
61+
</div>
62+
63+
{/* Info Section */}
64+
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-6">
65+
<h3 className="text-lg font-semibold mb-4 text-center">How FanTag Works</h3>
66+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 text-center">
67+
<div className="space-y-2">
68+
<div className="text-2xl">🎨</div>
69+
<h4 className="font-medium">Creators Register</h4>
70+
<p className="text-sm text-gray-600 dark:text-gray-400">
71+
Artists, musicians, and creators claim their .fantoken.eth domain
72+
</p>
73+
</div>
74+
<div className="space-y-2">
75+
<div className="text-2xl">🎪</div>
76+
<h4 className="font-medium">Fans Follow</h4>
77+
<p className="text-sm text-gray-600 dark:text-gray-400">
78+
Fans who follow creators can claim subdomains like alice.creator.fantoken.eth
79+
</p>
80+
</div>
81+
<div className="space-y-2">
82+
<div className="text-2xl">🌐</div>
83+
<h4 className="font-medium">Web3 Identity</h4>
84+
<p className="text-sm text-gray-600 dark:text-gray-400">
85+
Build your decentralized identity with ENS and social connections
86+
</p>
87+
</div>
88+
</div>
89+
</div>
6490
</div>
65-
</div>
91+
)}
6692
</div>
6793
</div>
68-
</>
94+
</div>
6995
);
7096
};
7197

0 commit comments

Comments
 (0)