-
Notifications
You must be signed in to change notification settings - Fork 14
/
onChainNFT.sol
180 lines (164 loc) · 7.05 KB
/
onChainNFT.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//__/\\\\\\\\\\\\\\\_________________________________________________________________________________/\\\\\\\\\______/\\\\\\\\\\\\____
// _\/\\\///////////________________________________________________________________________________/\\\///////\\\___\/\\\////////\\\__
//___\/\\\_____________________________/\\\\\\\\___/\\\_____________________________________________\/\\\_____\/\\\___\/\\\______\//\\\_
//____\/\\\\\\\\\\\______/\\/\\\\\\____/\\\////\\\_\///___/\\/\\\\\\_______/\\\\\\\\______/\\\\\\\\__\/\\\\\\\\\\\/____\/\\\_______\/\\\_
//_____\/\\\///////______\/\\\////\\\__\//\\\\\\\\\__/\\\_\/\\\////\\\____/\\\/////\\\___/\\\/////\\\_\/\\\//////\\\____\/\\\_______\/\\\_
//______\/\\\_____________\/\\\__\//\\\__\///////\\\_\/\\\_\/\\\__\//\\\__/\\\\\\\\\\\___/\\\\\\\\\\\__\/\\\____\//\\\___\/\\\_______\/\\\_
//_______\/\\\_____________\/\\\___\/\\\__/\\_____\\\_\/\\\_\/\\\___\/\\\_\//\\///////___\//\\///////___\/\\\_____\//\\\__\/\\\_______/\\\__
//________\/\\\\\\\\\\\\\\\_\/\\\___\/\\\_\//\\\\\\\\__\/\\\_\/\\\___\/\\\__\//\\\\\\\\\\__\//\\\\\\\\\\_\/\\\______\//\\\_\/\\\\\\\\\\\\/___
//_________\///////////////__\///____\///___\////////___\///__\///____\///____\//////////____\//////////__\///________\///__\////////////_____
//______________________________________________________________________________________________________________________parker@engineerd.io____
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./Base64.sol";
contract onChainNFT is ERC721Enumerable, Ownable {
using Strings for uint256;
bool public paused = false;
mapping(uint256 => Word) public wordsToTokenId;
uint256 public stringLimit = 45;
struct Word {
string name;
string description;
string bgHue;
string textHue;
string value;
}
//string[] public wordValues = ["accomplish", "accepted", "absolutely", "admire", "achievment", "active"];
constructor() ERC721("onChainNFT", "OCN") {}
// public
function mint(string memory _userText) public payable {
uint256 supply = totalSupply();
bytes memory strBytes = bytes(_userText);
require(strBytes.length <= stringLimit, "String input exceeds limit.");
require(exists(_userText) != true, "String already exists!");
Word memory newWord = Word(
string(abi.encodePacked("NFT", uint256(supply + 1).toString())),
"This is our on-chain NFT",
randomNum(361, block.difficulty, supply).toString(),
randomNum(361, block.timestamp, supply).toString(),
_userText
);
if (msg.sender != owner()) {
require(msg.value >= 0.005 ether);
}
wordsToTokenId[supply + 1] = newWord; //Add word to mapping @tokenId
_safeMint(msg.sender, supply + 1);
}
function exists(string memory _text) public view returns (bool) {
bool result = false;
//totalSupply function starts at 1, as does out wordToTokenId mapping
for (uint256 i = 1; i <= totalSupply(); i++) {
string memory text = wordsToTokenId[i].value;
if (
keccak256(abi.encodePacked(text)) ==
keccak256(abi.encodePacked(_text))
) {
result = true;
}
}
return result;
}
function randomNum(
uint256 _mod,
uint256 _seed,
uint256 _salt
) public view returns (uint256) {
uint256 num = uint256(
keccak256(
abi.encodePacked(block.timestamp, msg.sender, _seed, _salt)
)
) % _mod;
return num;
}
function buildImage(uint256 _tokenId) private view returns (string memory) {
Word memory currentWord = wordsToTokenId[_tokenId];
string memory random = randomNum(361, 3, 3).toString();
return
Base64.encode(
bytes(
abi.encodePacked(
'<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">',
'<rect id="svg_11" height="600" width="503" y="0" x="0" fill="hsl(',
currentWord.bgHue,
',50%,25%)"/>',
'<text font-size="18" y="10%" x="5%" fill="hsl(',
random,
',100%,80%)">Some Text</text>',
'<text font-size="18" y="15%" x="5%" fill="hsl(',
random,
',100%,80%)">Some Text</text>',
'<text font-size="18" y="20%" x="5%" fill="hsl(',
random,
',100%,80%)">Some Text</text>',
'<text font-size="18" y="10%" x="80%" fill="hsl(',
random,
',100%,80%)">Token: ',
_tokenId.toString(),
"</text>",
'<text font-size="18" y="50%" x="50%" text-anchor="middle" fill="hsl(',
random,
',100%,80%)">',
currentWord.value,
"</text>",
"</svg>"
)
)
);
}
function buildMetadata(uint256 _tokenId)
private
view
returns (string memory)
{
Word memory currentWord = wordsToTokenId[_tokenId];
return
string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(
bytes(
abi.encodePacked(
'{"name":"',
currentWord.name,
'", "description":"',
currentWord.description,
'", "image": "',
"data:image/svg+xml;base64,",
buildImage(_tokenId),
'", "attributes": ',
"[",
'{"trait_type": "TextColor",',
'"value":"',
currentWord.textHue,
'"}',
"]",
"}"
)
)
)
)
);
}
function tokenURI(uint256 _tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(_tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
return buildMetadata(_tokenId);
}
//only owner
function withdraw() public payable onlyOwner {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
require(success);
}
}