Smart Contract

FlowRewardsMetadataViews

A.a45ead1cf1ca9eda.FlowRewardsMetadataViews

Valid From

85,389,685

Deployed

2d ago
Feb 25, 2026, 07:03:31 PM UTC

Dependents

3 imports
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