-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathReceiptRenderer.sol
115 lines (109 loc) · 4.37 KB
/
ReceiptRenderer.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import '@openzeppelin/contracts/utils/Base64.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
/// @title ReceiptRenderer
/// @author RabbitHole.gg
/// @dev This contract is used to render on-chain data for RabbitHole Receipts (ERC-721 standard)
contract ReceiptRenderer {
using Strings for uint256;
/// @dev generates the tokenURI for a given ERC-721 token ID
/// @param tokenId_ The token id to generate the URI for
/// @param questId_ The questId tied to the tokenId
/// @param totalParticipants_ The total number of participants in the quest
/// @param claimed_ Whether or not the token has been claimed
/// @param rewardAmount_ The amount of reward tokens that the user is eligible for
/// @param rewardAddress_ The address of the reward token
/// @return encoded JSON following the generic OpenSea metadata standard
function generateTokenURI(
uint tokenId_,
string memory questId_,
uint totalParticipants_,
bool claimed_,
uint rewardAmount_,
address rewardAddress_
) public view virtual returns (string memory) {
bytes memory dataURI = generateDataURI(
tokenId_,
questId_,
totalParticipants_,
claimed_,
rewardAmount_,
rewardAddress_
);
return string(abi.encodePacked('data:application/json;base64,', Base64.encode(dataURI)));
}
function generateDataURI(
uint tokenId_,
string memory questId_,
uint totalParticipants_,
bool claimed_,
uint rewardAmount_,
address rewardAddress_
) public view virtual returns (bytes memory) {
bytes memory attributes = abi.encodePacked(
'[',
generateAttribute('Quest ID', questId_),
',',
generateAttribute('Token ID', tokenId_.toString()),
',',
generateAttribute('Total Participants', totalParticipants_.toString()),
',',
generateAttribute('Claimed', claimed_ ? 'true' : 'false'),
',',
generateAttribute('Reward Amount', rewardAmount_.toString()),
',',
generateAttribute('Reward Address', Strings.toHexString(uint160(rewardAddress_), 20)),
']'
);
bytes memory dataURI = abi.encodePacked(
'{',
'"name": "RabbitHole.gg Receipt #',
tokenId_.toString(),
'",',
'"description": "RabbitHole.gg Receipts are used to claim rewards from completed quests.",',
'"image": "',
generateSVG(tokenId_, questId_),
'",',
'"attributes": ',
attributes,
'}'
);
return dataURI;
}
/// @dev generates an attribute object for an ERC-721 token
/// @param key The key for the attribute
/// @param value The value for the attribute
function generateAttribute(string memory key, string memory value) public pure returns (string memory) {
bytes memory attribute = abi.encodePacked(
'{',
'"trait_type": "',
key,
'",',
'"value": "',
value,
'"',
'}'
);
return string(attribute);
}
/// @dev generates the on-chain SVG for an ERC-721 token ID
/// @param tokenId_ The token id to generate the svg for
/// @param questId_ The questId tied to the tokenId
/// @return encoded JSON for an SVG image
function generateSVG(uint tokenId_, string memory questId_) public pure returns (string memory) {
bytes memory svg = abi.encodePacked(
'<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350">',
'<style>.base { fill: white; font-family: serif; font-size: 14px; }</style>',
'<rect width="100%" height="100%" fill="black" />',
'<text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #',
questId_,
'</text>',
'<text x="70%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #',
tokenId_,
'</text>',
'</svg>'
);
return string(abi.encodePacked('data:image/svg+xml;base64,', Base64.encode(svg)));
}
}