@flowtyio/flow-contracts 0.0.18 → 0.1.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/Burner.cdc +44 -0
- package/contracts/FlowStorageFees.cdc +37 -39
- package/contracts/FlowToken.cdc +77 -89
- package/contracts/FungibleToken.cdc +121 -130
- package/contracts/FungibleTokenMetadataViews.cdc +38 -41
- package/contracts/MetadataViews.cdc +356 -390
- package/contracts/NonFungibleToken.cdc +149 -117
- package/contracts/TokenForwarding.cdc +19 -11
- package/contracts/ViewResolver.cdc +41 -8
- package/contracts/dapper/DapperUtilityCoin.cdc +106 -39
- package/contracts/dapper/FlowUtilityToken.cdc +107 -40
- package/contracts/example/ExampleNFT.cdc +419 -0
- package/contracts/example/ExampleToken.cdc +302 -0
- package/contracts/flow-utils/AddressUtils.cdc +20 -23
- package/contracts/flow-utils/ArrayUtils.cdc +10 -11
- package/contracts/flow-utils/ScopedFTProviders.cdc +24 -19
- package/contracts/flow-utils/ScopedNFTProviders.cdc +27 -26
- package/contracts/flow-utils/StringUtils.cdc +24 -37
- package/contracts/lost-and-found/FeeEstimator.cdc +14 -22
- package/contracts/lost-and-found/LostAndFound.cdc +180 -172
- package/contracts/lost-and-found/LostAndFoundHelper.cdc +12 -12
- package/contracts/nft-catalog/NFTCatalog.cdc +60 -64
- package/contracts/nft-catalog/NFTCatalogAdmin.cdc +28 -27
- package/flow.json +27 -1
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// Burner is a contract that can facilitate the destruction of any resource on flow.
|
|
2
|
+
///
|
|
3
|
+
/// Contributors
|
|
4
|
+
/// - Austin Kline - https://twitter.com/austin_flowty
|
|
5
|
+
/// - Deniz Edincik - https://twitter.com/bluesign
|
|
6
|
+
/// - Bastian Müller - https://twitter.com/turbolent
|
|
7
|
+
access(all) contract Burner {
|
|
8
|
+
/// When Crescendo (Cadence 1.0) is released, custom destructors will be removed from cadece.
|
|
9
|
+
/// Burnable is an interface meant to replace this lost feature, allowing anyone to add a callback
|
|
10
|
+
/// method to ensure they do not destroy something which is not meant to be,
|
|
11
|
+
/// or to add logic based on destruction such as tracking the supply of a FT Collection
|
|
12
|
+
///
|
|
13
|
+
/// NOTE: The only way to see benefit from this interface
|
|
14
|
+
/// is to always use the burn method in this contract. Anyone who owns a resource can always elect **not**
|
|
15
|
+
/// to destroy a resource this way
|
|
16
|
+
access(all) resource interface Burnable {
|
|
17
|
+
access(contract) fun burnCallback()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// burn is a global method which will destroy any resource it is given.
|
|
21
|
+
/// If the provided resource implements the Burnable interface,
|
|
22
|
+
/// it will call the burnCallback method and then destroy afterwards.
|
|
23
|
+
access(all) fun burn(_ r: @AnyResource) {
|
|
24
|
+
if let s <- r as? @{Burnable} {
|
|
25
|
+
s.burnCallback()
|
|
26
|
+
destroy s
|
|
27
|
+
} else if let arr <- r as? @[AnyResource] {
|
|
28
|
+
while arr.length > 0 {
|
|
29
|
+
let item <- arr.removeFirst()
|
|
30
|
+
self.burn(<-item)
|
|
31
|
+
}
|
|
32
|
+
destroy arr
|
|
33
|
+
} else if let dict <- r as? @{HashableStruct: AnyResource} {
|
|
34
|
+
let keys = dict.keys
|
|
35
|
+
while keys.length > 0 {
|
|
36
|
+
let item <- dict.remove(key: keys.removeFirst())!
|
|
37
|
+
self.burn(<-item)
|
|
38
|
+
}
|
|
39
|
+
destroy dict
|
|
40
|
+
} else {
|
|
41
|
+
destroy r
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -17,29 +17,29 @@
|
|
|
17
17
|
import "FungibleToken"
|
|
18
18
|
import "FlowToken"
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
access(all) contract FlowStorageFees {
|
|
21
21
|
|
|
22
22
|
// Emitted when the amount of storage capacity an account has per reserved Flow token changes
|
|
23
|
-
|
|
23
|
+
access(all) event StorageMegaBytesPerReservedFLOWChanged(_ storageMegaBytesPerReservedFLOW: UFix64)
|
|
24
24
|
|
|
25
25
|
// Emitted when the minimum amount of Flow tokens that an account needs to have reserved for storage capacity changes.
|
|
26
|
-
|
|
26
|
+
access(all) event MinimumStorageReservationChanged(_ minimumStorageReservation: UFix64)
|
|
27
27
|
|
|
28
28
|
// Defines how much storage capacity every account has per reserved Flow token.
|
|
29
29
|
// definition is written per unit of flow instead of the inverse,
|
|
30
30
|
// so there is no loss of precision calculating storage from flow,
|
|
31
31
|
// but there is loss of precision when calculating flow per storage.
|
|
32
|
-
|
|
32
|
+
access(all) var storageMegaBytesPerReservedFLOW: UFix64
|
|
33
33
|
|
|
34
34
|
// Defines the minimum amount of Flow tokens that every account needs to have reserved for storage capacity.
|
|
35
35
|
// If an account has less then this amount reserved by the end of any transaction it participated in, the transaction will fail.
|
|
36
|
-
|
|
36
|
+
access(all) var minimumStorageReservation: UFix64
|
|
37
37
|
|
|
38
38
|
// An administrator resource that can change the parameters of the FlowStorageFees smart contract.
|
|
39
|
-
|
|
39
|
+
access(all) resource Administrator {
|
|
40
40
|
|
|
41
41
|
// Changes the amount of storage capacity an account has per accounts' reserved storage FLOW.
|
|
42
|
-
|
|
42
|
+
access(all) fun setStorageMegaBytesPerReservedFLOW(_ storageMegaBytesPerReservedFLOW: UFix64) {
|
|
43
43
|
if FlowStorageFees.storageMegaBytesPerReservedFLOW == storageMegaBytesPerReservedFLOW {
|
|
44
44
|
return
|
|
45
45
|
}
|
|
@@ -48,7 +48,7 @@ pub contract FlowStorageFees {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Changes the minimum amount of FLOW an account has to have reserved.
|
|
51
|
-
|
|
51
|
+
access(all) fun setMinimumStorageReservation(_ minimumStorageReservation: UFix64) {
|
|
52
52
|
if FlowStorageFees.minimumStorageReservation == minimumStorageReservation {
|
|
53
53
|
return
|
|
54
54
|
}
|
|
@@ -63,19 +63,19 @@ pub contract FlowStorageFees {
|
|
|
63
63
|
///
|
|
64
64
|
/// Returns megabytes
|
|
65
65
|
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
|
|
66
|
-
|
|
66
|
+
access(all) fun calculateAccountCapacity(_ accountAddress: Address): UFix64 {
|
|
67
67
|
var balance = 0.0
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
let acct = getAccount(accountAddress)
|
|
69
|
+
|
|
70
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
71
|
+
balance = balanceRef.balance
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return self.accountBalanceToAccountStorageCapacity(balance)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/// calculateAccountsCapacity returns the storage capacity of a batch of accounts
|
|
78
|
-
|
|
78
|
+
access(all) fun calculateAccountsCapacity(_ accountAddresses: [Address]): [UFix64] {
|
|
79
79
|
let capacities: [UFix64] = []
|
|
80
80
|
for accountAddress in accountAddresses {
|
|
81
81
|
let capacity = self.calculateAccountCapacity(accountAddress)
|
|
@@ -88,19 +88,19 @@ pub contract FlowStorageFees {
|
|
|
88
88
|
// This is used to check if a transaction will fail because of any account being over the storage capacity
|
|
89
89
|
// The payer is an exception as its storage capacity is derived from its balance minus the maximum possible transaction fees
|
|
90
90
|
// (transaction fees if the execution effort is at the execution efort limit, a.k.a.: computation limit, a.k.a.: gas limit)
|
|
91
|
-
|
|
91
|
+
access(all) fun getAccountsCapacityForTransactionStorageCheck(accountAddresses: [Address], payer: Address, maxTxFees: UFix64): [UFix64] {
|
|
92
92
|
let capacities: [UFix64] = []
|
|
93
93
|
for accountAddress in accountAddresses {
|
|
94
94
|
var balance = 0.0
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
let acct = getAccount(accountAddress)
|
|
96
|
+
|
|
97
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
98
|
+
if accountAddress == payer {
|
|
99
|
+
// if the account is the payer, deduct the maximum possible transaction fees from the balance
|
|
100
|
+
balance = balanceRef.balance.saturatingSubtract(maxTxFees)
|
|
101
|
+
} else {
|
|
102
|
+
balance = balanceRef.balance
|
|
103
|
+
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
capacities.append(self.accountBalanceToAccountStorageCapacity(balance))
|
|
@@ -110,7 +110,7 @@ pub contract FlowStorageFees {
|
|
|
110
110
|
|
|
111
111
|
// accountBalanceToAccountStorageCapacity returns the storage capacity
|
|
112
112
|
// an account would have with given the flow balance of the account.
|
|
113
|
-
|
|
113
|
+
access(all) view fun accountBalanceToAccountStorageCapacity(_ balance: UFix64): UFix64 {
|
|
114
114
|
// get address token balance
|
|
115
115
|
if balance < self.minimumStorageReservation {
|
|
116
116
|
// if < then minimum return 0
|
|
@@ -123,15 +123,15 @@ pub contract FlowStorageFees {
|
|
|
123
123
|
|
|
124
124
|
// Amount in Flow tokens
|
|
125
125
|
// Returns megabytes
|
|
126
|
-
|
|
126
|
+
access(all) view fun flowToStorageCapacity(_ amount: UFix64): UFix64 {
|
|
127
127
|
return amount.saturatingMultiply(FlowStorageFees.storageMegaBytesPerReservedFLOW)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
// Amount in megabytes
|
|
131
131
|
// Returns Flow tokens
|
|
132
|
-
|
|
133
|
-
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0
|
|
134
|
-
return 0.0
|
|
132
|
+
access(all) view fun storageCapacityToFlow(_ amount: UFix64): UFix64 {
|
|
133
|
+
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0 {
|
|
134
|
+
return 0.0
|
|
135
135
|
}
|
|
136
136
|
// possible loss of precision
|
|
137
137
|
// putting the result back into `flowToStorageCapacity` might not yield the same result
|
|
@@ -139,9 +139,9 @@ pub contract FlowStorageFees {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// converts storage used from UInt64 Bytes to UFix64 Megabytes.
|
|
142
|
-
|
|
142
|
+
access(all) view fun convertUInt64StorageBytesToUFix64Megabytes(_ storage: UInt64): UFix64 {
|
|
143
143
|
// safe convert UInt64 to UFix64 (without overflow)
|
|
144
|
-
let f = UFix64(storage % 100000000
|
|
144
|
+
let f = UFix64(storage % 100000000) * 0.00000001 + UFix64(storage / 100000000)
|
|
145
145
|
// decimal point correction. Megabytes to bytes have a conversion of 10^-6 while UFix64 minimum value is 10^-8
|
|
146
146
|
let storageMb = f.saturatingMultiply(100.0)
|
|
147
147
|
return storageMb
|
|
@@ -151,13 +151,12 @@ pub contract FlowStorageFees {
|
|
|
151
151
|
///
|
|
152
152
|
/// The available balance of an account is its default token balance minus what is reserved for storage.
|
|
153
153
|
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
|
|
154
|
-
|
|
154
|
+
access(all) fun defaultTokenAvailableBalance(_ accountAddress: Address): UFix64 {
|
|
155
155
|
//get balance of account
|
|
156
156
|
let acct = getAccount(accountAddress)
|
|
157
157
|
var balance = 0.0
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.borrow<&FlowToken.Vault{FungibleToken.Balance}>() {
|
|
158
|
+
|
|
159
|
+
if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
|
|
161
160
|
balance = balanceRef.balance
|
|
162
161
|
}
|
|
163
162
|
|
|
@@ -171,9 +170,9 @@ pub contract FlowStorageFees {
|
|
|
171
170
|
///
|
|
172
171
|
/// The reserved balance of an account is its storage used multiplied by the storage cost per flow token.
|
|
173
172
|
/// The reserved balance is at least the minimum storage reservation.
|
|
174
|
-
|
|
173
|
+
access(all) view fun defaultTokenReservedBalance(_ accountAddress: Address): UFix64 {
|
|
175
174
|
let acct = getAccount(accountAddress)
|
|
176
|
-
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.
|
|
175
|
+
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.storage.used))
|
|
177
176
|
// at least self.minimumStorageReservation should be reserved
|
|
178
177
|
if reserved < self.minimumStorageReservation {
|
|
179
178
|
reserved = self.minimumStorageReservation
|
|
@@ -187,7 +186,6 @@ pub contract FlowStorageFees {
|
|
|
187
186
|
self.minimumStorageReservation = 0.0 // or 0 kb of minimum storage reservation
|
|
188
187
|
|
|
189
188
|
let admin <- create Administrator()
|
|
190
|
-
self.account.save(<-admin, to: /storage/storageFeesAdmin)
|
|
189
|
+
self.account.storage.save(<-admin, to: /storage/storageFeesAdmin)
|
|
191
190
|
}
|
|
192
191
|
}
|
|
193
|
-
|
package/contracts/FlowToken.cdc
CHANGED
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
import "FungibleToken"
|
|
2
2
|
import "MetadataViews"
|
|
3
3
|
import "FungibleTokenMetadataViews"
|
|
4
|
-
import "
|
|
4
|
+
import "Burner"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
access(all) contract FlowToken: FungibleToken {
|
|
7
7
|
|
|
8
8
|
// Total supply of Flow tokens in existence
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Event that is emitted when the contract is created
|
|
12
|
-
pub event TokensInitialized(initialSupply: UFix64)
|
|
9
|
+
access(all) var totalSupply: UFix64
|
|
13
10
|
|
|
14
11
|
// Event that is emitted when tokens are withdrawn from a Vault
|
|
15
|
-
|
|
12
|
+
access(all) event TokensWithdrawn(amount: UFix64, from: Address?)
|
|
16
13
|
|
|
17
14
|
// Event that is emitted when tokens are deposited to a Vault
|
|
18
|
-
|
|
15
|
+
access(all) event TokensDeposited(amount: UFix64, to: Address?)
|
|
19
16
|
|
|
20
17
|
// Event that is emitted when new tokens are minted
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// Event that is emitted when tokens are destroyed
|
|
24
|
-
pub event TokensBurned(amount: UFix64)
|
|
18
|
+
access(all) event TokensMinted(amount: UFix64)
|
|
25
19
|
|
|
26
20
|
// Event that is emitted when a new minter resource is created
|
|
27
|
-
|
|
21
|
+
access(all) event MinterCreated(allowedAmount: UFix64)
|
|
28
22
|
|
|
29
23
|
// Event that is emitted when a new burner resource is created
|
|
30
|
-
|
|
24
|
+
access(all) event BurnerCreated()
|
|
31
25
|
|
|
32
26
|
// Vault
|
|
33
27
|
//
|
|
@@ -41,16 +35,38 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
41
35
|
// out of thin air. A special Minter resource needs to be defined to mint
|
|
42
36
|
// new tokens.
|
|
43
37
|
//
|
|
44
|
-
|
|
38
|
+
access(all) resource Vault: FungibleToken.Vault {
|
|
45
39
|
|
|
46
40
|
// holds the balance of a users tokens
|
|
47
|
-
|
|
41
|
+
access(all) var balance: UFix64
|
|
48
42
|
|
|
49
43
|
// initialize the balance at resource creation time
|
|
50
44
|
init(balance: UFix64) {
|
|
51
45
|
self.balance = balance
|
|
52
46
|
}
|
|
53
47
|
|
|
48
|
+
/// Called when a fungible token is burned via the `Burner.burn()` method
|
|
49
|
+
access(contract) fun burnCallback() {
|
|
50
|
+
if self.balance > 0.0 {
|
|
51
|
+
FlowToken.totalSupply = FlowToken.totalSupply - self.balance
|
|
52
|
+
}
|
|
53
|
+
self.balance = 0.0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
|
|
57
|
+
access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
|
|
58
|
+
return {self.getType(): true}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
access(all) view fun isSupportedVaultType(type: Type): Bool {
|
|
62
|
+
if (type == self.getType()) { return true } else { return false }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Asks if the amount can be withdrawn from this vault
|
|
66
|
+
access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
|
|
67
|
+
return amount <= self.balance
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
// withdraw
|
|
55
71
|
//
|
|
56
72
|
// Function that takes an integer amount as an argument
|
|
@@ -60,7 +76,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
60
76
|
// created Vault to the context that called so it can be deposited
|
|
61
77
|
// elsewhere.
|
|
62
78
|
//
|
|
63
|
-
|
|
79
|
+
access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
|
|
64
80
|
self.balance = self.balance - amount
|
|
65
81
|
emit TokensWithdrawn(amount: amount, from: self.owner?.address)
|
|
66
82
|
return <-create Vault(balance: amount)
|
|
@@ -73,7 +89,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
73
89
|
// It is allowed to destroy the sent Vault because the Vault
|
|
74
90
|
// was a temporary holder of the tokens. The Vault's balance has
|
|
75
91
|
// been consumed and therefore can be destroyed.
|
|
76
|
-
|
|
92
|
+
access(all) fun deposit(from: @{FungibleToken.Vault}) {
|
|
77
93
|
let vault <- from as! @FlowToken.Vault
|
|
78
94
|
self.balance = self.balance + vault.balance
|
|
79
95
|
emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
|
|
@@ -81,19 +97,13 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
81
97
|
destroy vault
|
|
82
98
|
}
|
|
83
99
|
|
|
84
|
-
destroy() {
|
|
85
|
-
if self.balance > 0.0 {
|
|
86
|
-
FlowToken.totalSupply = FlowToken.totalSupply - self.balance
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
100
|
/// Get all the Metadata Views implemented by FlowToken
|
|
91
101
|
///
|
|
92
102
|
/// @return An array of Types defining the implemented views. This value will be used by
|
|
93
103
|
/// developers to know which parameter to pass to the resolveView() method.
|
|
94
104
|
///
|
|
95
|
-
|
|
96
|
-
return FlowToken.
|
|
105
|
+
access(all) view fun getViews(): [Type]{
|
|
106
|
+
return FlowToken.getContractViews(resourceType: nil)
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
/// Get a Metadata View from FlowToken
|
|
@@ -101,8 +111,12 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
101
111
|
/// @param view: The Type of the desired view.
|
|
102
112
|
/// @return A structure representing the requested view.
|
|
103
113
|
///
|
|
104
|
-
|
|
105
|
-
return FlowToken.
|
|
114
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
115
|
+
return FlowToken.resolveContractView(resourceType: nil, viewType: view)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
access(all) fun createEmptyVault(): @{FungibleToken.Vault} {
|
|
119
|
+
return <-create Vault(balance: 0.0)
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
|
|
@@ -113,14 +127,16 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
113
127
|
// and store the returned Vault in their storage in order to allow their
|
|
114
128
|
// account to be able to receive deposits of this token type.
|
|
115
129
|
//
|
|
116
|
-
|
|
130
|
+
access(all) fun createEmptyVault(vaultType: Type): @FlowToken.Vault {
|
|
117
131
|
return <-create Vault(balance: 0.0)
|
|
118
132
|
}
|
|
119
133
|
|
|
120
|
-
|
|
134
|
+
/// Gets a list of the metadata views that this contract supports
|
|
135
|
+
access(all) view fun getContractViews(resourceType: Type?): [Type] {
|
|
121
136
|
return [Type<FungibleTokenMetadataViews.FTView>(),
|
|
122
137
|
Type<FungibleTokenMetadataViews.FTDisplay>(),
|
|
123
|
-
Type<FungibleTokenMetadataViews.FTVaultData>()
|
|
138
|
+
Type<FungibleTokenMetadataViews.FTVaultData>(),
|
|
139
|
+
Type<FungibleTokenMetadataViews.TotalSupply>()]
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
/// Get a Metadata View from FlowToken
|
|
@@ -128,17 +144,17 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
128
144
|
/// @param view: The Type of the desired view.
|
|
129
145
|
/// @return A structure representing the requested view.
|
|
130
146
|
///
|
|
131
|
-
|
|
132
|
-
switch
|
|
147
|
+
access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
|
|
148
|
+
switch viewType {
|
|
133
149
|
case Type<FungibleTokenMetadataViews.FTView>():
|
|
134
150
|
return FungibleTokenMetadataViews.FTView(
|
|
135
|
-
ftDisplay: self.
|
|
136
|
-
ftVaultData: self.
|
|
151
|
+
ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTDisplay>()) as! FungibleTokenMetadataViews.FTDisplay?,
|
|
152
|
+
ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type<FungibleTokenMetadataViews.FTVaultData>()) as! FungibleTokenMetadataViews.FTVaultData?
|
|
137
153
|
)
|
|
138
154
|
case Type<FungibleTokenMetadataViews.FTDisplay>():
|
|
139
155
|
let media = MetadataViews.Media(
|
|
140
156
|
file: MetadataViews.HTTPFile(
|
|
141
|
-
url:
|
|
157
|
+
url: FlowToken.getLogoURI()
|
|
142
158
|
),
|
|
143
159
|
mediaType: "image/svg+xml"
|
|
144
160
|
)
|
|
@@ -146,7 +162,7 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
146
162
|
return FungibleTokenMetadataViews.FTDisplay(
|
|
147
163
|
name: "FLOW Network Token",
|
|
148
164
|
symbol: "FLOW",
|
|
149
|
-
description: "FLOW is the
|
|
165
|
+
description: "FLOW is the native token for the Flow blockchain. It is required for securing the network, transaction fees, storage fees, staking, FLIP voting and may be used by applications built on the Flow Blockchain",
|
|
150
166
|
externalURL: MetadataViews.ExternalURL("https://flow.com"),
|
|
151
167
|
logos: medias,
|
|
152
168
|
socials: {
|
|
@@ -154,57 +170,50 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
154
170
|
}
|
|
155
171
|
)
|
|
156
172
|
case Type<FungibleTokenMetadataViews.FTVaultData>():
|
|
173
|
+
let vaultRef = FlowToken.account.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(from: /storage/flowTokenVault)
|
|
174
|
+
?? panic("Could not borrow reference to the contract's Vault!")
|
|
157
175
|
return FungibleTokenMetadataViews.FTVaultData(
|
|
158
176
|
storagePath: /storage/flowTokenVault,
|
|
159
177
|
receiverPath: /public/flowTokenReceiver,
|
|
160
178
|
metadataPath: /public/flowTokenBalance,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
createEmptyVaultFunction: (fun (): @FungibleToken.Vault {
|
|
166
|
-
return <-FlowToken.createEmptyVault()
|
|
179
|
+
receiverLinkedType: Type<&{FungibleToken.Receiver, FungibleToken.Vault}>(),
|
|
180
|
+
metadataLinkedType: Type<&{FungibleToken.Balance, FungibleToken.Vault}>(),
|
|
181
|
+
createEmptyVaultFunction: (fun (): @{FungibleToken.Vault} {
|
|
182
|
+
return <-vaultRef.createEmptyVault()
|
|
167
183
|
})
|
|
168
184
|
)
|
|
185
|
+
case Type<FungibleTokenMetadataViews.TotalSupply>():
|
|
186
|
+
return FungibleTokenMetadataViews.TotalSupply(totalSupply: FlowToken.totalSupply)
|
|
169
187
|
}
|
|
170
188
|
return nil
|
|
171
189
|
}
|
|
172
190
|
|
|
173
|
-
|
|
191
|
+
access(all) resource Administrator {
|
|
174
192
|
// createNewMinter
|
|
175
193
|
//
|
|
176
194
|
// Function that creates and returns a new minter resource
|
|
177
195
|
//
|
|
178
|
-
|
|
196
|
+
access(all) fun createNewMinter(allowedAmount: UFix64): @Minter {
|
|
179
197
|
emit MinterCreated(allowedAmount: allowedAmount)
|
|
180
198
|
return <-create Minter(allowedAmount: allowedAmount)
|
|
181
199
|
}
|
|
182
|
-
|
|
183
|
-
// createNewBurner
|
|
184
|
-
//
|
|
185
|
-
// Function that creates and returns a new burner resource
|
|
186
|
-
//
|
|
187
|
-
pub fun createNewBurner(): @Burner {
|
|
188
|
-
emit BurnerCreated()
|
|
189
|
-
return <-create Burner()
|
|
190
|
-
}
|
|
191
200
|
}
|
|
192
201
|
|
|
193
202
|
// Minter
|
|
194
203
|
//
|
|
195
204
|
// Resource object that token admin accounts can hold to mint new tokens.
|
|
196
205
|
//
|
|
197
|
-
|
|
206
|
+
access(all) resource Minter {
|
|
198
207
|
|
|
199
208
|
// the amount of tokens that the minter is allowed to mint
|
|
200
|
-
|
|
209
|
+
access(all) var allowedAmount: UFix64
|
|
201
210
|
|
|
202
211
|
// mintTokens
|
|
203
212
|
//
|
|
204
213
|
// Function that mints new tokens, adds them to the total supply,
|
|
205
214
|
// and returns them to the calling context.
|
|
206
215
|
//
|
|
207
|
-
|
|
216
|
+
access(all) fun mintTokens(amount: UFix64): @FlowToken.Vault {
|
|
208
217
|
pre {
|
|
209
218
|
amount > UFix64(0): "Amount minted must be greater than zero"
|
|
210
219
|
amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
|
|
@@ -220,55 +229,34 @@ pub contract FlowToken: FungibleToken, ViewResolver {
|
|
|
220
229
|
}
|
|
221
230
|
}
|
|
222
231
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
pub resource Burner {
|
|
228
|
-
|
|
229
|
-
// burnTokens
|
|
230
|
-
//
|
|
231
|
-
// Function that destroys a Vault instance, effectively burning the tokens.
|
|
232
|
-
//
|
|
233
|
-
// Note: the burned tokens are automatically subtracted from the
|
|
234
|
-
// total supply in the Vault destructor.
|
|
235
|
-
//
|
|
236
|
-
pub fun burnTokens(from: @FungibleToken.Vault) {
|
|
237
|
-
let vault <- from as! @FlowToken.Vault
|
|
238
|
-
let amount = vault.balance
|
|
239
|
-
destroy vault
|
|
240
|
-
emit TokensBurned(amount: amount)
|
|
241
|
-
}
|
|
232
|
+
/// Gets the Flow Logo XML URI from storage
|
|
233
|
+
access(all) fun getLogoURI(): String {
|
|
234
|
+
return FlowToken.account.storage.copy<String>(from: /storage/flowTokenLogoURI) ?? ""
|
|
242
235
|
}
|
|
243
236
|
|
|
244
|
-
init(adminAccount:
|
|
237
|
+
init(adminAccount: auth(Storage, Capabilities) &Account) {
|
|
245
238
|
self.totalSupply = 0.0
|
|
246
239
|
|
|
247
240
|
// Create the Vault with the total supply of tokens and save it in storage
|
|
248
241
|
//
|
|
249
242
|
let vault <- create Vault(balance: self.totalSupply)
|
|
250
|
-
|
|
243
|
+
|
|
244
|
+
adminAccount.storage.save(<-vault, to: /storage/flowTokenVault)
|
|
251
245
|
|
|
252
246
|
// Create a public capability to the stored Vault that only exposes
|
|
253
247
|
// the `deposit` method through the `Receiver` interface
|
|
254
248
|
//
|
|
255
|
-
adminAccount.
|
|
256
|
-
|
|
257
|
-
target: /storage/flowTokenVault
|
|
258
|
-
)
|
|
249
|
+
let receiverCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault)
|
|
250
|
+
adminAccount.capabilities.publish(receiverCapability, at: /public/flowTokenReceiver)
|
|
259
251
|
|
|
260
252
|
// Create a public capability to the stored Vault that only exposes
|
|
261
253
|
// the `balance` field through the `Balance` interface
|
|
262
254
|
//
|
|
263
|
-
adminAccount.
|
|
264
|
-
|
|
265
|
-
target: /storage/flowTokenVault
|
|
266
|
-
)
|
|
255
|
+
let balanceCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault)
|
|
256
|
+
adminAccount.capabilities.publish(balanceCapability, at: /public/flowTokenBalance)
|
|
267
257
|
|
|
268
258
|
let admin <- create Administrator()
|
|
269
|
-
adminAccount.save(<-admin, to: /storage/flowTokenAdmin)
|
|
259
|
+
adminAccount.storage.save(<-admin, to: /storage/flowTokenAdmin)
|
|
270
260
|
|
|
271
|
-
// Emit an event that shows that the contract was initialized
|
|
272
|
-
emit TokensInitialized(initialSupply: self.totalSupply)
|
|
273
261
|
}
|
|
274
262
|
}
|