Smart Contract
FlowRewardsMetadataViews
A.a45ead1cf1ca9eda.FlowRewardsMetadataViews
1import FlowRewardsRegistry from 0xa45ead1cf1ca9eda
2
3/// This contract defines the views available for metadata retrieval from FlowRewards NFTs
4///
5access(all) contract FlowRewardsMetadataViews {
6
7 /// A rich data structure capturing the overview of a given NFT
8 ///
9 access(all) struct LockOverview {
10 /// The id of the corresponding NFT
11 access(all) let id: UInt64
12 /// The sequence number of the NFT AKA the order this NFT was minted in
13 access(all) let sequence: UInt64
14 /// The tier of the associated NFT
15 access(all) let tier: UInt8
16 /// The tier name of the associated NFT
17 access(all) let tierName: String
18 /// The timestamp at which the NFT was minted
19 access(all) let mintedTimestamp: UFix64
20 /// All lockup entries executed by associated NFT
21 access(all) let lockups: [{FlowRewardsRegistry.Lockup}]
22 /// The total value locked under the NFT
23 access(all) let totalLocked: UFix64
24 /// The total boost amount in rewards under the NFT
25 access(all) let totalRewards: UFix64
26 /// The total value that can be distributed as locked funds
27 access(all) let allowableLockedDistribution: UFix64
28 /// The total value that has been claimed as locked funds
29 access(all) let lockedClaimed: UFix64
30 /// The total value that can be distributed as rewards
31 access(all) let allowableRewardDistribution: UFix64
32 /// The total value that has been claimed as rewards
33 access(all) let rewardsClaimed: UFix64
34 /// The total remaining FLOW that can be distributed
35 access(all) let totalRemainingFlow: UFix64
36
37 view init(
38 id: UInt64,
39 sequence: UInt64,
40 tier: UInt8,
41 tierName: String,
42 lockups: [{FlowRewardsRegistry.Lockup}],
43 totalLocked: UFix64,
44 totalRewards: UFix64,
45 allowableLockedDistribution: UFix64,
46 lockedClaimed: UFix64,
47 allowableRewardDistribution: UFix64,
48 rewardsClaimed: UFix64
49 ) {
50 pre {
51 lockups.length > 0: "Rewards NFTs cannot exist without at least 1 lockup"
52 }
53 self.id = id
54 self.sequence = sequence
55 self.tier = tier
56 self.tierName = tierName
57 self.mintedTimestamp = lockups[0].timestamp
58 self.lockups = lockups
59 self.totalLocked = totalLocked
60 self.totalRewards = totalRewards
61 self.allowableLockedDistribution = allowableLockedDistribution
62 self.lockedClaimed = lockedClaimed
63 self.allowableRewardDistribution = allowableRewardDistribution
64 self.rewardsClaimed = rewardsClaimed
65 self.totalRemainingFlow = totalLocked + totalRewards - lockedClaimed - rewardsClaimed
66 }
67 }
68
69 /// A data structure intended to render metadata for a given NFT into an SVG string
70 ///
71 access(all) struct interface Renderer {
72 access(all) fun render(
73 metadata: {String: AnyStruct}
74 ): String
75 }
76
77 /// A renderer that renders the metadata of a given NFT into an SVG string, depicting a display related to locked
78 /// and rewards values
79 ///
80 access(all) struct LockSVGRenderer : Renderer {
81 /// The svg template to be rendered given NFT metadata
82 access(all) let template: [String]
83
84 init(template: [String]) {
85 pre {
86 template.length == 12:
87 "Expected 12 elements in the template - template length=".concat(template.length.toString())
88 }
89 self.template = template
90 }
91
92
93 /// Renders the SVG template with the given NFT metadata
94 ///
95 /// @param metadata: The metadata of the NFT to be rendered with values expected for:
96 /// - id: UInt64
97 /// - tier: String
98 /// - totalLocked: UFix64
99 /// - totalRewards: UFix64
100 /// - lockedClaimed: UFix64
101 /// - rewardsClaimed: UFix64
102 ///
103 /// @return: The SVG string rendered with the given metadata. If utilizing in an NFT view, this string should be
104 /// base64 encoded
105 ///
106 access(all) fun render(
107 metadata: {String: AnyStruct}
108 ): String {
109 // Access the metadata values
110 let id = metadata["id"] as! UInt64? ?? panic("Malformed metadata - missing id")
111 let tier = metadata["tierName"] as! String? ?? panic("Malformed metadata - missing tierName")
112 let totalLocked = metadata["totalLocked"] as! UFix64? ?? panic("Malformed metadata - missing totalLocked")
113 let totalRewards = metadata["totalRewards"] as! UFix64? ?? panic("Malformed metadata - missing totalRewards")
114 let lockedClaimed = metadata["lockedClaimed"] as! UFix64? ?? panic("Malformed metadata - missing lockedClaimed")
115 let rewardsClaimed = metadata["rewardsClaimed"] as! UFix64? ?? panic("Malformed metadata - missing rewardsClaimed")
116
117 // Convert to expected formats and render the SVG from the template
118 let lockedString = totalLocked.toString()
119 let rewardsString = (metadata["totalRewards"] as! UFix64?)!.toString()
120 let remainingString = (totalLocked + totalRewards - lockedClaimed - rewardsClaimed).toString()
121 let truncatedLockedString = lockedString.slice(from: 0, upTo: lockedString.length - 6)
122 let truncatedRewardsString = rewardsString.slice(from: 0, upTo: rewardsString.length - 6)
123 let truncatedRemainingString = remainingString.slice(from: 0, upTo: remainingString.length - 6)
124 return self.template[0].concat(truncatedRemainingString)
125 .concat(self.template[1]).concat(truncatedRewardsString)
126 .concat(self.template[2]).concat(truncatedLockedString)
127 .concat(self.template[3]).concat(id.toString())
128 .concat(self.template[4]).concat(tier)
129 .concat(self.template[5]).concat(lockedString)
130 .concat(self.template[6]).concat(rewardsString)
131 .concat(self.template[7]).concat(remainingString)
132 .concat(self.template[8]).concat(lockedString)
133 .concat(self.template[9]).concat(rewardsString)
134 .concat(self.template[10]).concat(remainingString)
135 .concat(self.template[11])
136 }
137 }
138}
139