Smart Contract
HybridCustodyHelper
A.807c3d470888cc48.HybridCustodyHelper
1import HybridCustody from 0xd8a7e05a7ac670c0
2import Flunks from 0x807c3d470888cc48
3import Backpack from 0x807c3d470888cc48
4import NonFungibleToken from 0x1d7e57aa55817448
5import MetadataViews from 0x1d7e57aa55817448
6
7// Helper function to store HybirdCustody logics for Flunks & Backpacks
8access(all) contract HybridCustodyHelper {
9 access(all) event ContractInitialized()
10
11 access(all) fun parseUInt64(_ string: String) : UInt64? {
12 let chars : {Character : UInt64} = {
13 "0" : 0 ,
14 "1" : 1 ,
15 "2" : 2 ,
16 "3" : 3 ,
17 "4" : 4 ,
18 "5" : 5 ,
19 "6" : 6 ,
20 "7" : 7 ,
21 "8" : 8 ,
22 "9" : 9
23 }
24 var number : UInt64 = 0
25 var i = 0
26 while i < string.length {
27 if let n = chars[string[i]] {
28 number = number * 10 + n
29 } else {
30 return nil
31 }
32 i = i + 1
33 }
34 return number
35 }
36
37 access(all) fun getChildAccounts(parentAddress: Address): [Address] {
38 // Retrieve the account associated with the parent address
39 let parentAcct = getAccount(parentAddress)
40
41 // Attempt to borrow a reference to the parent's Manager resource via the public path
42 let parentPublicCapability = parentAcct.capabilities.borrow<&HybridCustody.Manager>(HybridCustody.ManagerPublicPath)
43
44 // Check if the borrowing was successful
45 if let parentManager = parentPublicCapability {
46 // Retrieve and return the child account addresses if the reference was successfully borrowed
47 return parentManager.getChildAddresses()
48 } else {
49 // Return an empty array if the reference could not be borrowed
50 return []
51 }
52 }
53
54 access(all) fun getChildAccountAddressHoldingFlunksTokenId(ownerAddress: Address, tokenID: UInt64): Address? {
55 let flunksTokenIDs: [UInt64] = []
56 let ownerAccount = getAccount(ownerAddress)
57 let mainCollectionFlunksTokenIDs = ownerAccount.capabilities.borrow<&Flunks.Collection>(Flunks.CollectionPublicPath)?.getIDs() ?? []
58 if mainCollectionFlunksTokenIDs.contains(tokenID) {
59 return ownerAddress
60 }
61
62 // Retrieve linked accounts tokenIDs
63 let childAccounts = HybridCustodyHelper.getChildAccounts(parentAddress: ownerAddress)
64 for childAddress in childAccounts {
65 let childAccount = getAccount(childAddress)
66 let childFlunksCollection = childAccount.capabilities.borrow<&Flunks.Collection>(Flunks.CollectionPublicPath)
67 let childFlunksCollectionTokenIDs: [UInt64] = childFlunksCollection?.getIDs() ?? []
68 if childFlunksCollectionTokenIDs.contains(tokenID) {
69 return childAddress
70 }
71 }
72
73 return nil
74}
75
76 access(all) fun getChildAccountAddressHoldingBackpackTokenId(ownerAddress: Address, tokenID: UInt64): Address? {
77 let backpackTokenIds: [UInt64] = []
78 let ownerAccount = getAccount(ownerAddress)
79 let mainCollectionBackpackTokenIDs: [UInt64] = ownerAccount.capabilities.borrow<&Backpack.Collection>(Backpack.CollectionPublicPath)?.getIDs() ?? []
80 if mainCollectionBackpackTokenIDs.contains(tokenID) {
81 return ownerAddress
82 }
83
84 // Retrieve linked accounts tokenIDs
85 let childAccounts = HybridCustodyHelper.getChildAccounts(parentAddress: ownerAddress)
86 for childAddress in childAccounts {
87 let childAccount = getAccount(childAddress)
88 let childCollection = childAccount.capabilities.borrow<&Backpack.Collection>(Backpack.CollectionPublicPath)
89 let childCollectionTokenIds: [UInt64] = childCollection?.getIDs() ?? []
90 if childCollectionTokenIds.contains(tokenID) {
91 return childAddress
92 }
93 }
94
95 return nil
96 }
97
98 access(all) fun getBackpackSlots(ownerAddress: Address, tokenID: UInt64): UInt64 {
99 if let trueOwnerAddress = HybridCustodyHelper.getChildAccountAddressHoldingBackpackTokenId(ownerAddress: ownerAddress, tokenID: tokenID) {
100 let trueOwnerAccount = getAccount(trueOwnerAddress)
101 if let trueOwnerCollection = trueOwnerAccount.capabilities.borrow<&Backpack.Collection>(Backpack.CollectionPublicPath) {
102 let item = trueOwnerCollection.borrowNFT(tokenID)
103 if let traitsView = item?.resolveView(Type<MetadataViews.Traits>()) {
104 let traits = traitsView as! MetadataViews.Traits?
105 for trait in traits?.traits! {
106 if trait.name == "slots" || trait.name == "Slots" {
107 return HybridCustodyHelper.parseUInt64(trait.value as! String) ?? 0
108 }
109 }
110 }
111 }
112 }
113
114 // Default slot to be 0
115 return 0
116 }
117
118 access(all) fun getFlunksTokenIDsFromAllLinkedAccounts(ownerAddress: Address): [UInt64] {
119 var flunksTokenIDs: [UInt64] = []
120 let ownerAccount = getAccount(ownerAddress)
121 let mainCollectionFlunksTokenIDs: [UInt64] = ownerAccount.capabilities.borrow<&Flunks.Collection>(Flunks.CollectionPublicPath)?.getIDs() ?? []
122 for tokenID in mainCollectionFlunksTokenIDs {
123 flunksTokenIDs.append(tokenID)
124 }
125
126 // Retrieve linked accounts tokenIDs
127 let childAccounts = HybridCustodyHelper.getChildAccounts(parentAddress: ownerAddress)
128 for childAddress in childAccounts {
129 let childAccount = getAccount(childAddress)
130 let childFlunksCollection = childAccount.capabilities.borrow<&Flunks.Collection>(Flunks.CollectionPublicPath)
131 let childFlunksCollectionTokenIDs: [UInt64] = childFlunksCollection?.getIDs() ?? []
132 for tokenID in childFlunksCollectionTokenIDs {
133 flunksTokenIDs.append(tokenID)
134 }
135 }
136
137 return flunksTokenIDs
138 }
139
140 access(all) fun getBackpackTokenIDsFromAllLinkedAccounts(ownerAddress: Address): [UInt64] {
141 var backpackTokenIDs: [UInt64] = []
142 let ownerAccount = getAccount(ownerAddress)
143 let mainCollectionBackpackTokenIDs = ownerAccount.capabilities.borrow<&Backpack.Collection>(Backpack.CollectionPublicPath)?.getIDs() ?? []
144 for tokenID in mainCollectionBackpackTokenIDs {
145 backpackTokenIDs.append(tokenID)
146 }
147
148 // Retrieve linked accounts tokenIDs
149 let childAccounts = HybridCustodyHelper.getChildAccounts(parentAddress: ownerAddress)
150 for childAddress in childAccounts {
151 let childAccount = getAccount(childAddress)
152 let childBackpackCollection = childAccount.capabilities.borrow<&Backpack.Collection>(Backpack.CollectionPublicPath)
153 let childBackpackCollectionTokenIDs: [UInt64] = childBackpackCollection?.getIDs() ?? []
154 for tokenID in childBackpackCollectionTokenIDs {
155 backpackTokenIDs.append(tokenID)
156 }
157 }
158
159 return backpackTokenIDs
160 }
161
162
163 access(all) fun forceRelinkCollections(signer: auth(SaveValue, Capabilities, Storage, BorrowValue) &Account) {
164 // if the account doesn't already have Flunks
165 if signer.storage.borrow<&Flunks.Collection>(from: Flunks.CollectionStoragePath) == nil {
166 // create a new empty collection
167 let collection <- Flunks.createEmptyCollection(nftType: Type<@Flunks.Collection>())
168 // save it to the account
169 signer.storage.save(<-collection, to: Flunks.CollectionStoragePath)
170 // create a public capability for the collection
171 let cap = signer.capabilities.storage.issue<&Flunks.Collection>(Flunks.CollectionStoragePath)
172 signer.capabilities.publish(cap, at: Flunks.CollectionPublicPath)
173 } else {
174 // Unlink the existing collection (if any)
175 signer.capabilities.unpublish(Flunks.CollectionPublicPath)
176
177 // Re-link
178 let cap = signer.capabilities.storage.issue<&Flunks.Collection>(Flunks.CollectionStoragePath)
179 signer.capabilities.publish(cap, at: Flunks.CollectionPublicPath)
180 }
181
182 // if the account doesn't already have Backpack
183 if signer.storage.borrow<&Backpack.Collection>(from: Backpack.CollectionStoragePath) == nil {
184 // create a new empty collection
185 let collection <- Backpack.createEmptyCollection(nftType: Type<@Backpack.Collection>())
186 // save it to the account
187 signer.storage.save(<-collection, to: Backpack.CollectionStoragePath)
188 // create a public capability for the collection
189 let cap = signer.capabilities.storage.issue<&Backpack.Collection>(Backpack.CollectionStoragePath)
190 signer.capabilities.publish(cap, at: Backpack.CollectionPublicPath)
191 } else {
192 // Unlink the existing collection (if any)
193 signer.capabilities.unpublish(Backpack.CollectionPublicPath)
194
195 // Re-link
196 let cap = signer.capabilities.storage.issue<&Backpack.Collection>(Backpack.CollectionStoragePath)
197 signer.capabilities.publish(cap, at: Backpack.CollectionPublicPath)
198 }
199 }
200
201
202 init() {
203 emit ContractInitialized()
204 }
205}