Skip to content

Commit

Permalink
change nft color based on build count
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPereira committed Jan 11, 2024
1 parent e345305 commit c944c51
Show file tree
Hide file tree
Showing 22 changed files with 1,324 additions and 84 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
1. Impliment chainlink function to fetch build count from BG api
2. Set up minting on frontend with mainnet ens lookup that is passed as arg to mint function
3. Hook up subgraph for speedy display of the nft collection
4. Figure out if account abstraction is possible for the minting to pay users mint fees
5. Ship it
4. Different color background depending on number of builds
1. 0 - 4 builds gets bronze
2. 5 - 9 builds gets silver
3. 10+ builds gets rainbow or gold
5. Figure out if account abstraction is possible for the minting to pay users mint fees

## Resources

### NFT metadata example

- ipfs://bafybeibc5sgo2plmjkq2tzmhrn54bk3crhnc23zd2msg4ea7a4pxrkgfna/2222

### Subgraphs

- https://thegraph.com/docs/en/developing/creating-a-subgraph/#writing-mappings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,29 @@ import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

/**
* Basic setup for dynamic svg nft project
*
*
* MemberData.ensName sourced from frontend that queries mainnet ens registry
* MemberData.buildCount comes from chainlink function
*/
contract BuidlGuidlNft is ERC721 {
contract BuidlCountNft is ERC721 {
struct MemberData {
string ensName;
uint8 buildCount;
}

mapping(address => MemberData) public s_memberToData;
mapping(address => bool) private hasMinted;
uint256 private s_tokenCounter;
string private constant base64EncodedSvgPrefix =
"data:image/svg+xml;base64,";
string[] private s_backgroundColors = [
"#4f46e5",
"#ef4444",
"#10b981",
"#3b82f6",
"#f59e0b"
];

string public zeroToFourBuilds = "#52525b";
string public fiveToNineBuilds = "#2563eb";
string public tenPlusBuilds = "#4f46e5";

/**
* First NFT minted has tokenId of 0
*/
constructor() ERC721("Buidl Guidl", "BGDL") {
constructor() ERC721("Buidl Counter", "BDLC") {
s_tokenCounter = 0;
}

Expand All @@ -45,13 +40,20 @@ contract BuidlGuidlNft is ERC721 {
function svgToImageURI(
uint256 tokenId
) public view returns (string memory) {
uint256 colorIndex = tokenId % s_backgroundColors.length;
string memory color = s_backgroundColors[colorIndex];
string memory svgPart1 = buildSvgPart1(color);
string memory svgPart2 = buildSvgPart2(color, tokenId);
address ownerAddr = ownerOf(tokenId);

string memory color;
if (s_memberToData[ownerAddr].buildCount < 5) {
color = zeroToFourBuilds;
} else if (s_memberToData[ownerAddr].buildCount < 10) {
color = fiveToNineBuilds;
} else {
color = tenPlusBuilds;
}
string memory svgTop = buildSvgTop(color);
string memory svgBottom = buildSvgBottom(color, tokenId);
string memory svgBase64Encoded = Base64.encode(
bytes(string(abi.encodePacked(svgPart1, svgPart2)))
bytes(string(abi.encodePacked(svgTop, svgBottom)))
);
return
string(abi.encodePacked(base64EncodedSvgPrefix, svgBase64Encoded));
Expand All @@ -63,7 +65,7 @@ contract BuidlGuidlNft is ERC721 {
* @param backgroundColor used to fill background of svg and text of ensName
*/
function buildSvgPart1(
function buildSvgTop(
string memory backgroundColor
) private pure returns (string memory) {
return
Expand All @@ -73,10 +75,11 @@ contract BuidlGuidlNft is ERC721 {
'<rect width="500" height="375" fill="',
backgroundColor,
'"/>',
'<g transform="translate(25, 25) scale(2.1)">',
'<path fill="white" fill-rule="evenodd" clip-rule="evenodd" d="M14.8867 10.1643V19.4598H17.2209V24.8329H22.9973V19.4598H27.0062V30.206L20.7013 42.0233L13.5031 41.9146L6.30486 42.0233L0 30.206V19.4598H3.99065V24.8329H9.78528V19.4598H12.3588V1.26395C12.3588 0.565889 12.9247 0 13.6228 0C14.1263 0 14.561 0.2944 14.7642 0.72045C15.4031 0.965338 16.0466 1.61238 16.7119 2.28137C17.5022 3.07602 18.3232 3.90163 19.2039 4.12095C20.0931 4.34242 20.7524 4.10563 21.4951 3.83887C22.2743 3.559 23.1453 3.24616 24.4701 3.39486C25.4635 3.51174 25.9901 4.16046 26.5791 4.88586C27.3621 5.85033 28.2552 6.95035 30.5016 7.11611L30.4874 7.12612C29.0491 8.14179 27.084 9.5295 24.0327 9.2581C23.0785 9.17577 22.4062 8.86812 21.7616 8.57316C20.8429 8.15279 19.9805 7.75817 18.4385 8.07819C16.7695 8.41302 15.9262 9.20317 15.2849 9.80403C15.1447 9.9354 15.0141 10.0577 14.8867 10.1643Z"/>',
'<g transform="translate(20, 27) scale(1.15)">',
'<path fill="white" d="M63.1218 27.7353V76.2086H42.8441V61.9337C42.8441 55.6618 37.7624 50.5771 31.5185 50.5771C25.2747 50.5771 20.193 55.6618 20.193 61.9337V76.2086H0V27.7353H11.818V34.7392C11.818 37.7366 14.2505 40.1603 17.2345 40.1603C20.2186 40.1603 22.6511 37.7366 22.6511 34.7392V27.7353H40.3781V34.7095C40.3781 37.7069 42.8106 40.1306 45.7947 40.1306C48.7787 40.1306 51.2112 37.7069 51.2112 34.7095V27.7353H63.1218Z"/>',
'<path d="M28.7643 2.18495V32.263H34.0339V18.7778C34.0339 18.7778 35.3804 16.0081 40.2893 17.2299C46.7851 18.8468 54.7881 17.7511 59.9257 8.45259C44.3573 13.5802 43.9403 -4.04034 28.7643 2.18495Z" fill="white"/>',
"</g>"
'<text fill="white" x="90" y="115" font-size="77">BuidlGuidl</text>',
'<text fill="white" x="97" y="115" font-size="77">BuidlGuidl</text>',
'<rect fill="white" x="0" y="160" width="500" height="60"/>'
)
);
Expand All @@ -87,13 +90,13 @@ contract BuidlGuidlNft is ERC721 {
* @param textColor text color for buildCount number (matches the background color)
* @param tokenId to get the address of the NFT owner used to lookup dynamic ens name and buildCount
*/
function buildSvgPart2(
function buildSvgBottom(
string memory textColor,
uint256 tokenId
) private view returns (string memory) {
address ownerAddr = ownerOf(tokenId);

string memory buildCount = Strings.toString(
string memory buildCountString = Strings.toString(
s_memberToData[ownerAddr].buildCount
);
string memory ensName = s_memberToData[ownerAddr].ensName;
Expand Down Expand Up @@ -133,7 +136,7 @@ contract BuidlGuidlNft is ERC721 {
'<text x="440" y="300" font-size="40" font-weight="bold" text-anchor="middle" dominant-baseline="central" fill="',
textColor,
'">',
buildCount,
buildCountString,
"</text>",
'<text fill="white" x="25" y="315" font-size="43" font-weight="bold">Builds Shipped</text>',
"</svg>"
Expand All @@ -147,8 +150,14 @@ contract BuidlGuidlNft is ERC721 {
* 3. mint new NFT
*
*/
function minNft() public {
function minNft(uint8 _buidlCount) public {
require(!hasMinted[msg.sender], "Address has already minted an NFT");
s_memberToData[msg.sender] = MemberData({
ensName: "",
buildCount: uint8(_buidlCount)
});
_safeMint(msg.sender, s_tokenCounter);
hasMinted[msg.sender] = true;
s_tokenCounter++;
}

Expand Down Expand Up @@ -180,4 +189,8 @@ contract BuidlGuidlNft is ERC721 {
)
);
}

function getBuidlCount(address _memberAddr) public view returns (uint8) {
return s_memberToData[_memberAddr].buildCount;
}
}
3 changes: 3 additions & 0 deletions packages/foundry/deployments/1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"networkName": "Mainnet"
}
3 changes: 3 additions & 0 deletions packages/foundry/deployments/31337.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"networkName": "Anvil"
}
2 changes: 1 addition & 1 deletion packages/foundry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"compile": "forge compile",
"deploy": "forge build --build-info --build-info-path out/build-info/ && forge script script/Deploy.s.sol --rpc-url ${1:-default_network} --broadcast --legacy && node script/generateTsAbis.js",
"deploy:verify": "forge build --build-info --build-info-path out/build-info/ && forge script script/Deploy.s.sol --rpc-url ${1:-default_network} --broadcast --legacy --verify ; node script/generateTsAbis.js",
"fork": "anvil --fork-url ${0:-mainnet} --chain-id 31337 --config-out localhost.json",
"fork": "anvil --fork-url $MAINNET_RPC_URL --chain-id 31337 --config-out localhost.json",
"generate": "node script/generateAccount.js",
"lint": "forge fmt",
"test": "forge test",
Expand Down
6 changes: 3 additions & 3 deletions packages/foundry/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.19;

import "./DeployHelpers.s.sol";
import {BuidlGuidlNft} from "../contracts/BuidlGuidlNft.sol";
import {BuidlCountNft} from "../contracts/BuidlCountNft.sol";

contract DeployScript is ScaffoldETHDeploy {
error InvalidPrivateKey(string);
Expand All @@ -16,11 +16,11 @@ contract DeployScript is ScaffoldETHDeploy {
}
vm.startBroadcast(deployerPrivateKey);

BuidlGuidlNft bgNft = new BuidlGuidlNft();
BuidlCountNft buidlCountNft = new BuidlCountNft();
console.logString(
string.concat(
"bgNft contract deployed at: ",
vm.toString(address(bgNft))
vm.toString(address(buidlCountNft))
)
);
vm.stopBroadcast();
Expand Down
13 changes: 0 additions & 13 deletions packages/foundry/svg/BuidlGuidl.svg

This file was deleted.

16 changes: 16 additions & 0 deletions packages/foundry/svg/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions packages/foundry/svg/nft.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions packages/foundry/svg/radialGradient.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c944c51

Please sign in to comment.