@flowtyio/flow-contracts 0.0.9 → 0.0.11
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/README.md +11 -11
- package/contracts/hybrid-custody/CapabilityDelegator.cdc +174 -0
- package/contracts/hybrid-custody/CapabilityFactory.cdc +105 -0
- package/contracts/hybrid-custody/CapabilityFilter.cdc +199 -0
- package/contracts/hybrid-custody/HybridCustody.cdc +1202 -0
- package/contracts/hybrid-custody/factories/FTAllFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +10 -0
- package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +10 -0
- package/flow.json +22 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -40,17 +40,17 @@ Currently, the list includes:
|
|
|
40
40
|
| NonFungibleToken | 0x1d7e57aa55817448 | 0x631e88ae7f1d7c20 |
|
|
41
41
|
| MetadataViews | 0x1d7e57aa55817448 | 0x631e88ae7f1d7c20 |
|
|
42
42
|
| ViewResolver | 0x1d7e57aa55817448 | 0x631e88ae7f1d7c20 |
|
|
43
|
-
| HybridCusody | 0x294e44e1ec6993c6 |
|
|
44
|
-
| CapabilityFactory | 0x294e44e1ec6993c6 |
|
|
45
|
-
| CapabilityFilter | 0x294e44e1ec6993c6 |
|
|
46
|
-
| CapabilityDelegator | 0x294e44e1ec6993c6 |
|
|
47
|
-
| FTAllFactory | 0x294e44e1ec6993c6 |
|
|
48
|
-
| FTBalanceFactory | 0x294e44e1ec6993c6 |
|
|
49
|
-
| FTProviderFactory | 0x294e44e1ec6993c6 |
|
|
50
|
-
| FTReceiverFactory | 0x294e44e1ec6993c6 |
|
|
51
|
-
| NFTCollectionPublicFactory | 0x294e44e1ec6993c6 |
|
|
52
|
-
| NFTProviderAndCollectionPublicFactory | 0x294e44e1ec6993c6 |
|
|
53
|
-
| NFTProviderFactory | 0x294e44e1ec6993c6 |
|
|
43
|
+
| HybridCusody | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
44
|
+
| CapabilityFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
45
|
+
| CapabilityFilter | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
46
|
+
| CapabilityDelegator | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
47
|
+
| FTAllFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
48
|
+
| FTBalanceFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
49
|
+
| FTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
50
|
+
| FTReceiverFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
51
|
+
| NFTCollectionPublicFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
52
|
+
| NFTProviderAndCollectionPublicFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
53
|
+
| NFTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
## Using a contract
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/// CapabilityDelegator is a contract used to share Capabiltities to other accounts. It is used by the
|
|
2
|
+
/// HybridCustody contract to allow more flexible sharing of Capabilities when an app wants to share things
|
|
3
|
+
/// that aren't the NFT-standard interface types.
|
|
4
|
+
///
|
|
5
|
+
/// Inside of CapabilityDelegator is a resource called `Delegator` which maintains a mapping of public and private
|
|
6
|
+
/// Capabilities. They cannot and should not be mixed. A public `Delegator` is able to be borrowed by anyone, whereas a
|
|
7
|
+
/// private `Delegator` can only be borrowed from the child account when you have access to the full `ChildAccount`
|
|
8
|
+
/// resource.
|
|
9
|
+
///
|
|
10
|
+
pub contract CapabilityDelegator {
|
|
11
|
+
|
|
12
|
+
/* --- Canonical Paths --- */
|
|
13
|
+
//
|
|
14
|
+
pub let StoragePath: StoragePath
|
|
15
|
+
pub let PrivatePath: PrivatePath
|
|
16
|
+
pub let PublicPath: PublicPath
|
|
17
|
+
|
|
18
|
+
/* --- Events --- */
|
|
19
|
+
//
|
|
20
|
+
pub event DelegatorCreated(id: UInt64)
|
|
21
|
+
pub event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool)
|
|
22
|
+
|
|
23
|
+
/// Private interface for Capability retrieval
|
|
24
|
+
///
|
|
25
|
+
pub resource interface GetterPrivate {
|
|
26
|
+
pub fun getPrivateCapability(_ type: Type): Capability? {
|
|
27
|
+
post {
|
|
28
|
+
result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
pub fun findFirstPrivateType(_ type: Type): Type?
|
|
32
|
+
pub fun getAllPrivate(): [Capability]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Exposes public Capability retrieval
|
|
36
|
+
///
|
|
37
|
+
pub resource interface GetterPublic {
|
|
38
|
+
pub fun getPublicCapability(_ type: Type): Capability? {
|
|
39
|
+
post {
|
|
40
|
+
result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type "
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
pub fun findFirstPublicType(_ type: Type): Type?
|
|
45
|
+
pub fun getAllPublic(): [Capability]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// This Delegator is used to store Capabilities, partitioned by public and private access with corresponding
|
|
49
|
+
/// GetterPublic and GetterPrivate conformances.AccountCapabilityController
|
|
50
|
+
///
|
|
51
|
+
pub resource Delegator: GetterPublic, GetterPrivate {
|
|
52
|
+
access(self) let privateCapabilities: {Type: Capability}
|
|
53
|
+
access(self) let publicCapabilities: {Type: Capability}
|
|
54
|
+
|
|
55
|
+
// ------ Begin Getter methods
|
|
56
|
+
//
|
|
57
|
+
/// Returns the public Capability of the given Type if it exists
|
|
58
|
+
///
|
|
59
|
+
pub fun getPublicCapability(_ type: Type): Capability? {
|
|
60
|
+
return self.publicCapabilities[type]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Returns the private Capability of the given Type if it exists
|
|
64
|
+
///
|
|
65
|
+
///
|
|
66
|
+
/// @param type: Type of the Capability to retrieve
|
|
67
|
+
/// @return Capability of the given Type if it exists, nil otherwise
|
|
68
|
+
///
|
|
69
|
+
pub fun getPrivateCapability(_ type: Type): Capability? {
|
|
70
|
+
return self.privateCapabilities[type]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Returns all public Capabilities
|
|
74
|
+
///
|
|
75
|
+
/// @return List of all public Capabilities
|
|
76
|
+
///
|
|
77
|
+
pub fun getAllPublic(): [Capability] {
|
|
78
|
+
return self.publicCapabilities.values
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Returns all private Capabilities
|
|
82
|
+
///
|
|
83
|
+
/// @return List of all private Capabilities
|
|
84
|
+
///
|
|
85
|
+
pub fun getAllPrivate(): [Capability] {
|
|
86
|
+
return self.privateCapabilities.values
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Returns the first public Type that is a subtype of the given Type
|
|
90
|
+
///
|
|
91
|
+
/// @param type: Type to check for subtypes
|
|
92
|
+
/// @return First public Type that is a subtype of the given Type, nil otherwise
|
|
93
|
+
///
|
|
94
|
+
pub fun findFirstPublicType(_ type: Type): Type? {
|
|
95
|
+
for t in self.publicCapabilities.keys {
|
|
96
|
+
if t.isSubtype(of: type) {
|
|
97
|
+
return t
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// Returns the first private Type that is a subtype of the given Type
|
|
105
|
+
///
|
|
106
|
+
/// @param type: Type to check for subtypes
|
|
107
|
+
/// @return First private Type that is a subtype of the given Type, nil otherwise
|
|
108
|
+
///
|
|
109
|
+
pub fun findFirstPrivateType(_ type: Type): Type? {
|
|
110
|
+
for t in self.privateCapabilities.keys {
|
|
111
|
+
if t.isSubtype(of: type) {
|
|
112
|
+
return t
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return nil
|
|
117
|
+
}
|
|
118
|
+
// ------- End Getter methods
|
|
119
|
+
|
|
120
|
+
/// Adds a Capability to the Delegator
|
|
121
|
+
///
|
|
122
|
+
/// @param cap: Capability to add
|
|
123
|
+
/// @param isPublic: Whether the Capability should be public or private
|
|
124
|
+
///
|
|
125
|
+
pub fun addCapability(cap: Capability, isPublic: Bool) {
|
|
126
|
+
pre {
|
|
127
|
+
cap.check<&AnyResource>(): "Invalid Capability provided"
|
|
128
|
+
}
|
|
129
|
+
if isPublic {
|
|
130
|
+
self.publicCapabilities.insert(key: cap.getType(), cap)
|
|
131
|
+
} else {
|
|
132
|
+
self.privateCapabilities.insert(key: cap.getType(), cap)
|
|
133
|
+
}
|
|
134
|
+
emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: isPublic, active: true)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/// Removes a Capability from the Delegator
|
|
138
|
+
///
|
|
139
|
+
/// @param cap: Capability to remove
|
|
140
|
+
///
|
|
141
|
+
pub fun removeCapability(cap: Capability) {
|
|
142
|
+
if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) {
|
|
143
|
+
emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if let removedPrivate = self.privateCapabilities.remove(key: cap.getType()) {
|
|
147
|
+
emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: false, active: false)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
init() {
|
|
152
|
+
self.privateCapabilities = {}
|
|
153
|
+
self.publicCapabilities = {}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/// Creates a new Delegator and returns it
|
|
158
|
+
///
|
|
159
|
+
/// @return Newly created Delegator
|
|
160
|
+
///
|
|
161
|
+
pub fun createDelegator(): @Delegator {
|
|
162
|
+
let delegator <- create Delegator()
|
|
163
|
+
emit DelegatorCreated(id: delegator.uuid)
|
|
164
|
+
return <- delegator
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
init() {
|
|
168
|
+
let identifier = "CapabilityDelegator_".concat(self.account.address.toString())
|
|
169
|
+
self.StoragePath = StoragePath(identifier: identifier)!
|
|
170
|
+
self.PrivatePath = PrivatePath(identifier: identifier)!
|
|
171
|
+
self.PublicPath = PublicPath(identifier: identifier)!
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/// # Capability Factory
|
|
2
|
+
///
|
|
3
|
+
/// This contract defines a Factory interface and a Manager resource to contain Factory implementations, as well as a
|
|
4
|
+
/// Getter interface for retrieval of contained Factories.
|
|
5
|
+
///
|
|
6
|
+
/// A Factory is defines a method getCapability() which defines the retrieval pattern of a Capability from a given
|
|
7
|
+
/// account at the specified path. This pattern arose out of a need to retrieve arbitrary & castable Capabilities from
|
|
8
|
+
/// an account under the static typing constraints inherent to Cadence.
|
|
9
|
+
///
|
|
10
|
+
/// The Manager resource is a container for Factories, and implements the Getter interface.
|
|
11
|
+
///
|
|
12
|
+
/// **Note:** It's generally an anti-pattern to pass around AuthAccount references; however, the need for castable
|
|
13
|
+
/// Capabilities is critical to the use case of Hybrid Custody. It's advised to use Factories sparingly and only for
|
|
14
|
+
/// cases where Capabilities must be castable by the caller.
|
|
15
|
+
///
|
|
16
|
+
pub contract CapabilityFactory {
|
|
17
|
+
|
|
18
|
+
pub let StoragePath: StoragePath
|
|
19
|
+
pub let PrivatePath: PrivatePath
|
|
20
|
+
pub let PublicPath: PublicPath
|
|
21
|
+
|
|
22
|
+
/// Factory structures a common interface for Capability retrieval from a given account at a specified path
|
|
23
|
+
///
|
|
24
|
+
pub struct interface Factory {
|
|
25
|
+
pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Getter defines an interface for retrieval of a Factory if contained within the implementing resource
|
|
29
|
+
///
|
|
30
|
+
pub resource interface Getter {
|
|
31
|
+
pub fun getSupportedTypes(): [Type]
|
|
32
|
+
pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}?
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Manager is a resource that contains Factories and implements the Getter interface for retrieval of contained
|
|
36
|
+
/// Factories
|
|
37
|
+
///
|
|
38
|
+
pub resource Manager: Getter {
|
|
39
|
+
/// Mapping of Factories indexed on Type of Capability they retrieve
|
|
40
|
+
pub let factories: {Type: {CapabilityFactory.Factory}}
|
|
41
|
+
|
|
42
|
+
/// Retrieves a list of Types supported by contained Factories
|
|
43
|
+
///
|
|
44
|
+
/// @return List of Types supported by the Manager
|
|
45
|
+
///
|
|
46
|
+
pub fun getSupportedTypes(): [Type] {
|
|
47
|
+
return self.factories.keys
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Retrieves a Factory from the Manager, returning it or nil if it doesn't exist
|
|
51
|
+
///
|
|
52
|
+
/// @param t: Type the Factory is indexed on
|
|
53
|
+
///
|
|
54
|
+
pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {
|
|
55
|
+
return self.factories[t]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Adds a Factory to the Manager, conditioned on the Factory not already existing
|
|
59
|
+
///
|
|
60
|
+
/// @param t: Type of Capability the Factory retrieves
|
|
61
|
+
/// @param f: Factory to add
|
|
62
|
+
///
|
|
63
|
+
pub fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
|
|
64
|
+
pre {
|
|
65
|
+
!self.factories.containsKey(t): "Factory of given type already exists"
|
|
66
|
+
}
|
|
67
|
+
self.factories[t] = f
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Updates a Factory in the Manager, adding if it didn't already exist
|
|
71
|
+
///
|
|
72
|
+
/// @param t: Type of Capability the Factory retrieves
|
|
73
|
+
/// @param f: Factory to replace existing Factory
|
|
74
|
+
///
|
|
75
|
+
pub fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
|
|
76
|
+
self.factories[t] = f
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Removes a Factory from the Manager, returning it or nil if it didn't exist
|
|
80
|
+
///
|
|
81
|
+
/// @param t: Type the Factory is indexed on
|
|
82
|
+
///
|
|
83
|
+
pub fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {
|
|
84
|
+
return self.factories.remove(key: t)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
init () {
|
|
88
|
+
self.factories = {}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Creates a Manager resource
|
|
93
|
+
///
|
|
94
|
+
/// @return Manager resource
|
|
95
|
+
pub fun createFactoryManager(): @Manager {
|
|
96
|
+
return <- create Manager()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
init() {
|
|
100
|
+
let identifier = "CapabilityFactory_".concat(self.account.address.toString())
|
|
101
|
+
self.StoragePath = StoragePath(identifier: identifier)!
|
|
102
|
+
self.PrivatePath = PrivatePath(identifier: identifier)!
|
|
103
|
+
self.PublicPath = PublicPath(identifier: identifier)!
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/// CapabilityFilter defines `Filter`, an interface to sit on top of a ChildAccount's capabilities. Requested
|
|
2
|
+
/// capabilities will only return if the filter's `allowed` method returns true.
|
|
3
|
+
///
|
|
4
|
+
/// Along with the `Filter` interface are three implementations:
|
|
5
|
+
/// - `DenylistFilter` - A filter which contains a mapping of denied Types
|
|
6
|
+
/// - `AllowlistFilter` - A filter which contains a mapping of allowed Types
|
|
7
|
+
/// - `AllowAllFilter` - A passthrough, all requested capabilities are allowed
|
|
8
|
+
///
|
|
9
|
+
pub contract CapabilityFilter {
|
|
10
|
+
|
|
11
|
+
/* --- Canonical Paths --- */
|
|
12
|
+
//
|
|
13
|
+
pub let StoragePath: StoragePath
|
|
14
|
+
pub let PublicPath: PublicPath
|
|
15
|
+
pub let PrivatePath: PrivatePath
|
|
16
|
+
|
|
17
|
+
/* --- Events --- */
|
|
18
|
+
//
|
|
19
|
+
pub event FilterUpdated(id: UInt64, filterType: Type, type: Type, active: Bool)
|
|
20
|
+
|
|
21
|
+
/// `Filter` is a simple interface with methods to determine if a Capability is allowed and retrieve details about
|
|
22
|
+
/// the Filter itself
|
|
23
|
+
///
|
|
24
|
+
pub resource interface Filter {
|
|
25
|
+
pub fun allowed(cap: Capability): Bool
|
|
26
|
+
pub fun getDetails(): AnyStruct
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// `DenylistFilter` is a `Filter` which contains a mapping of denied Types
|
|
30
|
+
///
|
|
31
|
+
pub resource DenylistFilter: Filter {
|
|
32
|
+
|
|
33
|
+
/// Represents the underlying types which should not ever be returned by a RestrictedChildAccount. The filter
|
|
34
|
+
/// will borrow a requested capability, and make sure that the type it gets back is not in the list of denied
|
|
35
|
+
/// types
|
|
36
|
+
access(self) let deniedTypes: {Type: Bool}
|
|
37
|
+
|
|
38
|
+
/// Adds a type to the mapping of denied types with a value of true
|
|
39
|
+
///
|
|
40
|
+
/// @param type: The type to add to the denied types mapping
|
|
41
|
+
///
|
|
42
|
+
pub fun addType(_ type: Type) {
|
|
43
|
+
self.deniedTypes.insert(key: type, true)
|
|
44
|
+
emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Removes a type from the mapping of denied types
|
|
48
|
+
///
|
|
49
|
+
/// @param type: The type to remove from the denied types mapping
|
|
50
|
+
///
|
|
51
|
+
pub fun removeType(_ type: Type) {
|
|
52
|
+
if let removed = self.deniedTypes.remove(key: type) {
|
|
53
|
+
emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Determines if a requested capability is allowed by this `Filter`
|
|
58
|
+
///
|
|
59
|
+
/// @param cap: The capability to check
|
|
60
|
+
/// @return: true if the capability is allowed, false otherwise
|
|
61
|
+
///
|
|
62
|
+
pub fun allowed(cap: Capability): Bool {
|
|
63
|
+
if let item = cap.borrow<&AnyResource>() {
|
|
64
|
+
return !self.deniedTypes.containsKey(item.getType())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Returns details about this filter
|
|
71
|
+
///
|
|
72
|
+
/// @return A struct containing details about this filter including this Filter's Type indexed on the `type`
|
|
73
|
+
/// key as well as types denied indexed on the `deniedTypes` key
|
|
74
|
+
///
|
|
75
|
+
pub fun getDetails(): AnyStruct {
|
|
76
|
+
return {
|
|
77
|
+
"type": self.getType(),
|
|
78
|
+
"deniedTypes": self.deniedTypes.keys
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
init() {
|
|
83
|
+
self.deniedTypes = {}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// `AllowlistFilter` is a `Filter` which contains a mapping of allowed Types
|
|
88
|
+
///
|
|
89
|
+
pub resource AllowlistFilter: Filter {
|
|
90
|
+
// allowedTypes
|
|
91
|
+
// Represents the set of underlying types which are allowed to be
|
|
92
|
+
// returned by a RestrictedChildAccount. The filter will borrow
|
|
93
|
+
// a requested capability, and make sure that the type it gets back is
|
|
94
|
+
// in the list of allowed types
|
|
95
|
+
access(self) let allowedTypes: {Type: Bool}
|
|
96
|
+
|
|
97
|
+
/// Adds a type to the mapping of allowed types with a value of true
|
|
98
|
+
///
|
|
99
|
+
/// @param type: The type to add to the allowed types mapping
|
|
100
|
+
///
|
|
101
|
+
pub fun addType(_ type: Type) {
|
|
102
|
+
self.allowedTypes.insert(key: type, true)
|
|
103
|
+
emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: true)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Removes a type from the mapping of allowed types
|
|
107
|
+
///
|
|
108
|
+
/// @param type: The type to remove from the denied types mapping
|
|
109
|
+
///
|
|
110
|
+
pub fun removeType(_ type: Type) {
|
|
111
|
+
if let removed = self.allowedTypes.remove(key: type) {
|
|
112
|
+
emit FilterUpdated(id: self.uuid, filterType: self.getType(), type: type, active: false)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Determines if a requested capability is allowed by this `Filter`
|
|
117
|
+
///
|
|
118
|
+
/// @param cap: The capability to check
|
|
119
|
+
/// @return: true if the capability is allowed, false otherwise
|
|
120
|
+
///
|
|
121
|
+
pub fun allowed(cap: Capability): Bool {
|
|
122
|
+
if let item = cap.borrow<&AnyResource>() {
|
|
123
|
+
return self.allowedTypes.containsKey(item.getType())
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Returns details about this filter
|
|
130
|
+
///
|
|
131
|
+
/// @return A struct containing details about this filter including this Filter's Type indexed on the `type`
|
|
132
|
+
/// key as well as types allowed indexed on the `allowedTypes` key
|
|
133
|
+
///
|
|
134
|
+
pub fun getDetails(): AnyStruct {
|
|
135
|
+
return {
|
|
136
|
+
"type": self.getType(),
|
|
137
|
+
"allowedTypes": self.allowedTypes.keys
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
init() {
|
|
142
|
+
self.allowedTypes = {}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// AllowAllFilter is a passthrough, all requested capabilities are allowed
|
|
147
|
+
///
|
|
148
|
+
pub resource AllowAllFilter: Filter {
|
|
149
|
+
/// Determines if a requested capability is allowed by this `Filter`
|
|
150
|
+
///
|
|
151
|
+
/// @param cap: The capability to check
|
|
152
|
+
/// @return: true since this filter is a passthrough
|
|
153
|
+
///
|
|
154
|
+
pub fun allowed(cap: Capability): Bool {
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Returns details about this filter
|
|
159
|
+
///
|
|
160
|
+
/// @return A struct containing details about this filter including this Filter's Type indexed on the `type`
|
|
161
|
+
/// key
|
|
162
|
+
///
|
|
163
|
+
pub fun getDetails(): AnyStruct {
|
|
164
|
+
return {
|
|
165
|
+
"type": self.getType()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// Creates a new `Filter` of the given type
|
|
171
|
+
///
|
|
172
|
+
/// @param t: The type of `Filter` to create
|
|
173
|
+
/// @return: A new instance of the given `Filter` type
|
|
174
|
+
///
|
|
175
|
+
pub fun create(_ t: Type): @AnyResource{Filter} {
|
|
176
|
+
post {
|
|
177
|
+
result.getType() == t
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
switch t {
|
|
181
|
+
case Type<@AllowAllFilter>():
|
|
182
|
+
return <- create AllowAllFilter()
|
|
183
|
+
case Type<@AllowlistFilter>():
|
|
184
|
+
return <- create AllowlistFilter()
|
|
185
|
+
case Type<@DenylistFilter>():
|
|
186
|
+
return <- create DenylistFilter()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
panic("unsupported type requested: ".concat(t.identifier))
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
init() {
|
|
193
|
+
let identifier = "CapabilityFilter_".concat(self.account.address.toString())
|
|
194
|
+
|
|
195
|
+
self.StoragePath = StoragePath(identifier: identifier)!
|
|
196
|
+
self.PublicPath = PublicPath(identifier: identifier)!
|
|
197
|
+
self.PrivatePath = PrivatePath(identifier: identifier)!
|
|
198
|
+
}
|
|
199
|
+
}
|