Smart Contract
FlowTokenHelper
A.6c1b12e35dca8863.FlowTokenHelper
1// FlowTokenHelper.cdc - Fixed for Cadence 1.0 (Standalone Version)
2access(all) contract FlowTokenHelper {
3
4 // =====================================
5 // EVENTS
6 // =====================================
7
8 access(all) event SafeTransferCompleted(from: Address, to: Address, amount: UFix64)
9 access(all) event BatchTransferCompleted(from: Address, recipients: UInt64, totalAmount: UFix64)
10 access(all) event TransferValidationFailed(from: Address, to: Address, amount: UFix64, reason: String)
11
12 // =====================================
13 // STRUCTS
14 // =====================================
15
16 access(all) struct TransferResult {
17 access(all) let success: Bool
18 access(all) let amount: UFix64
19 access(all) let recipient: Address
20 access(all) let error: String?
21
22 init(success: Bool, amount: UFix64, recipient: Address, error: String?) {
23 self.success = success
24 self.amount = amount
25 self.recipient = recipient
26 self.error = error
27 }
28 }
29
30 access(all) struct TokenBalance {
31 access(all) let address: Address
32 access(all) let balance: UFix64
33 access(all) let hasVault: Bool
34 access(all) let hasReceiver: Bool
35
36 init(address: Address, balance: UFix64, hasVault: Bool, hasReceiver: Bool) {
37 self.address = address
38 self.balance = balance
39 self.hasVault = hasVault
40 self.hasReceiver = hasReceiver
41 }
42 }
43
44 access(all) struct PayoutDistribution {
45 access(all) let recipient: Address
46 access(all) let amount: UFix64
47 access(all) let shares: UFix64
48
49 init(recipient: Address, amount: UFix64, shares: UFix64) {
50 self.recipient = recipient
51 self.amount = amount
52 self.shares = shares
53 }
54 }
55
56 // =====================================
57 // VALIDATION FUNCTIONS
58 // =====================================
59
60 access(all) fun validateTransfer(from: Address, to: Address, amount: UFix64): {String: Bool} {
61 let result: {String: Bool} = {}
62
63 // Check if addresses are valid
64 result["validFromAddress"] = FlowTokenHelper.isValidAddress(address: from)
65 result["validToAddress"] = FlowTokenHelper.isValidAddress(address: to)
66
67 // Check if amount is valid
68 result["validAmount"] = FlowTokenHelper.validateTransferAmount(amount: amount)
69
70 // Check if recipient has receiver capability
71 result["hasReceiver"] = FlowTokenHelper.hasFlowTokenReceiver(address: to)
72
73 // Check if sender has vault
74 result["hasVault"] = FlowTokenHelper.hasFlowTokenVault(address: from)
75
76 return result
77 }
78
79 access(all) fun validateTransferAmount(amount: UFix64): Bool {
80 return amount > 0.0 && amount <= 999999999.99999999 // Max reasonable amount
81 }
82
83 access(all) fun isValidAddress(address: Address): Bool {
84 // Basic address validation - check if account exists
85 let account = getAccount(address)
86 return true // Account exists if we can get it
87 }
88
89 // =====================================
90 // BALANCE CHECKING FUNCTIONS (Simplified)
91 // =====================================
92
93 access(all) fun getBalance(address: Address): TokenBalance? {
94 let account = getAccount(address)
95
96 // Simplified balance check without FungibleToken imports
97 // In a real implementation, you'd check the actual FlowToken vault
98 return TokenBalance(
99 address: address,
100 balance: account.balance, // Account's native FLOW balance
101 hasVault: true, // Assume true for simplicity
102 hasReceiver: true // Assume true for simplicity
103 )
104 }
105
106 access(all) fun getBatchBalances(addresses: [Address]): [TokenBalance] {
107 let balances: [TokenBalance] = []
108
109 for address in addresses {
110 if let balance = FlowTokenHelper.getBalance(address: address) {
111 balances.append(balance)
112 }
113 }
114
115 return balances
116 }
117
118 access(all) fun hasFlowTokenVault(address: Address): Bool {
119 // Simplified check - in production, check actual FlowToken vault capability
120 let account = getAccount(address)
121 return true // Assume all accounts have vaults
122 }
123
124 access(all) fun hasFlowTokenReceiver(address: Address): Bool {
125 // Simplified check - in production, check actual FlowToken receiver capability
126 let account = getAccount(address)
127 return true // Assume all accounts can receive tokens
128 }
129
130 // =====================================
131 // FORMATTING FUNCTIONS
132 // =====================================
133
134 access(all) fun formatTokenAmount(amount: UFix64): String {
135 if amount >= 1000000.0 {
136 let millions = amount / 1000000.0
137 return millions.toString().concat("M")
138 } else if amount >= 1000.0 {
139 let thousands = amount / 1000.0
140 return thousands.toString().concat("K")
141 } else {
142 return amount.toString()
143 }
144 }
145
146 access(all) fun formatForDisplay(amount: UFix64, decimals: UInt8): String {
147 // Format amount with specified decimal places
148 let integerPart = UInt64(amount)
149 let fractionalPart = amount - UFix64(integerPart)
150
151 if decimals == 0 {
152 return integerPart.toString()
153 }
154
155 // Simple decimal formatting
156 let multiplier = UFix64(decimals == 1 ? 10 : decimals == 2 ? 100 : 1000)
157 let fractionalInt = UInt64(fractionalPart * multiplier)
158
159 return integerPart.toString().concat(".").concat(fractionalInt.toString())
160 }
161
162 access(all) fun calculateTransactionFee(amount: UFix64): UFix64 {
163 // Simple fee calculation - can be customized
164 let baseFee: UFix64 = 0.001 // 0.001 FLOW base fee
165 let percentageFee = amount * 0.001 // 0.1% of amount
166
167 return baseFee + percentageFee
168 }
169
170 // =====================================
171 // PAYOUT DISTRIBUTION
172 // =====================================
173
174 access(all) fun distributePayout(
175 totalPayout: UFix64,
176 winners: [Address],
177 shares: [UFix64]
178 ): {Address: UFix64} {
179 pre {
180 winners.length == shares.length: "Winners and shares arrays must have the same length"
181 totalPayout > 0.0: "Total payout must be greater than 0"
182 }
183
184 let payouts: {Address: UFix64} = {}
185 var totalShares: UFix64 = 0.0
186
187 // Calculate total shares
188 for share in shares {
189 totalShares = totalShares + share
190 }
191
192 if totalShares == 0.0 {
193 return payouts
194 }
195
196 // Calculate individual payouts
197 var i = 0
198 while i < winners.length {
199 let winner = winners[i]
200 let share = shares[i]
201 let payout = (share / totalShares) * totalPayout
202
203 payouts[winner] = payout
204 i = i + 1
205 }
206
207 return payouts
208 }
209
210 access(all) fun calculatePayoutDistribution(
211 totalPayout: UFix64,
212 winners: [Address],
213 shares: [UFix64]
214 ): [PayoutDistribution] {
215 pre {
216 winners.length == shares.length: "Winners and shares arrays must have the same length"
217 }
218
219 let distributions: [PayoutDistribution] = []
220 var totalShares: UFix64 = 0.0
221
222 // Calculate total shares
223 for share in shares {
224 totalShares = totalShares + share
225 }
226
227 if totalShares == 0.0 {
228 return distributions
229 }
230
231 // Create distribution objects
232 var i = 0
233 while i < winners.length {
234 let winner = winners[i]
235 let share = shares[i]
236 let amount = (share / totalShares) * totalPayout
237
238 let distribution = PayoutDistribution(
239 recipient: winner,
240 amount: amount,
241 shares: share
242 )
243 distributions.append(distribution)
244 i = i + 1
245 }
246
247 return distributions
248 }
249
250 // =====================================
251 // UTILITY FUNCTIONS
252 // =====================================
253
254 access(all) fun convertToDisplayUnits(amount: UFix64): UFix64 {
255 // Convert from base units to display units if needed
256 return amount
257 }
258
259 access(all) fun convertFromDisplayUnits(amount: UFix64): UFix64 {
260 // Convert from display units to base units if needed
261 return amount
262 }
263
264 access(all) fun getMinimumBalance(): UFix64 {
265 return 0.001 // Minimum balance to maintain for transaction fees
266 }
267
268 access(all) fun getMaximumTransferAmount(): UFix64 {
269 return 999999999.99999999 // Maximum allowed transfer amount
270 }
271
272 // =====================================
273 // SECURITY FUNCTIONS
274 // =====================================
275
276 access(all) fun isTransferAmountSafe(amount: UFix64, senderBalance: UFix64): Bool {
277 let minimumBalance = FlowTokenHelper.getMinimumBalance()
278 return senderBalance >= (amount + minimumBalance)
279 }
280
281 access(all) fun validateBatchTransfer(recipients: [Address], amounts: [UFix64]): Bool {
282 pre {
283 recipients.length == amounts.length: "Recipients and amounts must have same length"
284 recipients.length > 0: "Must have at least one recipient"
285 }
286
287 // Validate each recipient and amount
288 var i = 0
289 while i < recipients.length {
290 let recipient = recipients[i]
291 let amount = amounts[i]
292
293 if !FlowTokenHelper.isValidAddress(address: recipient) {
294 return false
295 }
296
297 if !FlowTokenHelper.validateTransferAmount(amount: amount) {
298 return false
299 }
300
301 if !FlowTokenHelper.hasFlowTokenReceiver(address: recipient) {
302 return false
303 }
304
305 i = i + 1
306 }
307
308 return true
309 }
310
311 // =====================================
312 // CONTRACT INITIALIZATION
313 // =====================================
314
315 init() {
316 // Contract initialization
317 }
318}