Smart Contract
ToucansLockTokens
A.577a3c409c5dcb5e.ToucansLockTokens
1import FungibleToken from 0xf233dcee88fe0abe
2import ToucansTokens from 0x577a3c409c5dcb5e
3
4access(all) contract ToucansLockTokens {
5
6 access(all) entitlement ManagerOwner
7
8 access(all) struct LockedVaultDetails {
9 access(all) let lockedVaultUuid: UInt64
10 access(all) let recipient: Address
11 access(all) let vaultType: Type
12 access(all) let unlockTime: UFix64
13 access(all) let tokenInfo: ToucansTokens.TokenInfo
14 access(all) let amount: UFix64
15 access(all) let extra: {String: AnyStruct}
16
17 init(
18 lockedVaultUuid: UInt64,
19 recipient: Address,
20 vaultType: Type,
21 unlockTime: UFix64,
22 tokenInfo: ToucansTokens.TokenInfo,
23 amount: UFix64
24 ) {
25 self.lockedVaultUuid = lockedVaultUuid
26 self.recipient = recipient
27 self.vaultType = vaultType
28 self.unlockTime = unlockTime
29 self.tokenInfo = tokenInfo
30 self.amount = amount
31 self.extra = {}
32 }
33 }
34
35 access(all) resource LockedVault {
36 access(all) let details: LockedVaultDetails
37 access(contract) var vault: @{FungibleToken.Vault}?
38 // for extra metadata
39 access(self) var additions: @{String: AnyResource}
40
41 access(contract) fun withdrawVault(receiver: &{FungibleToken.Receiver}) {
42 pre {
43 receiver.owner!.address == self.details.recipient: "This LockedVault does not belong to the receiver."
44 getCurrentBlock().timestamp >= self.details.unlockTime: "This LockedVault is not ready to be unlocked."
45 }
46 let vault <- self.vault <- nil
47 receiver.deposit(from: <- vault!)
48 }
49
50 init(recipient: Address, unlockTime: UFix64, vault: @{FungibleToken.Vault}, tokenInfo: ToucansTokens.TokenInfo) {
51 self.details = LockedVaultDetails(
52 lockedVaultUuid: self.uuid,
53 recipient: recipient,
54 vaultType: vault.getType(),
55 unlockTime: unlockTime,
56 tokenInfo: tokenInfo,
57 amount: vault.balance
58 )
59 self.vault <- vault
60 self.additions <- {}
61 }
62 }
63
64 access(all) resource interface ManagerPublic {}
65
66 access(all) resource Manager: ManagerPublic {
67 access(self) let lockedVaults: @{UInt64: LockedVault}
68 access(self) let addressMap: {Address: [UInt64]}
69 // for extra metadata
70 access(self) var additions: @{String: AnyResource}
71
72 access(ManagerOwner) fun deposit(recipient: Address, unlockTime: UFix64, vault: @{FungibleToken.Vault}, tokenInfo: ToucansTokens.TokenInfo) {
73 pre {
74 tokenInfo.tokenType == vault.getType(): "Types are not the same"
75 }
76 let lockedVault: @LockedVault <- create LockedVault(recipient: recipient, unlockTime: unlockTime, vault: <- vault, tokenInfo: tokenInfo)
77 let recipient: Address = lockedVault.details.recipient
78 if self.addressMap[recipient] == nil {
79 self.addressMap[recipient] = [lockedVault.uuid]
80 } else {
81 self.addressMap[recipient]!.append(lockedVault.uuid)
82 }
83
84 self.lockedVaults[lockedVault.uuid] <-! lockedVault
85 }
86
87 access(all) fun claim(lockedVaultUuid: UInt64, receiver: &{FungibleToken.Receiver}) {
88 let lockedVault: @LockedVault <- self.lockedVaults.remove(key: lockedVaultUuid) ?? panic("This LockedVault does not exist.")
89 lockedVault.withdrawVault(receiver: receiver)
90 assert(lockedVault.vault == nil, message: "The withdraw did not execute correctly.")
91 destroy lockedVault
92 let indexOfUuid: Int = self.addressMap[receiver.owner!.address]!.firstIndex(of: lockedVaultUuid)!
93 self.addressMap[receiver.owner!.address]!.remove(at: indexOfUuid)
94 }
95
96 access(all) view fun getIDs(): [UInt64] {
97 return self.lockedVaults.keys
98 }
99
100 access(all) view fun getIDsForAddress(address: Address): [UInt64] {
101 return self.addressMap[address] ?? []
102 }
103
104 access(all) fun getLockedVaultInfos(): [LockedVaultDetails] {
105 let ids: [UInt64] = self.getIDs()
106 let vaults: [LockedVaultDetails] = []
107 for id in ids {
108 vaults.append(self.lockedVaults[id]?.details!)
109 }
110 return vaults
111 }
112
113 access(all) fun getLockedVaultInfosForAddress(address: Address): [LockedVaultDetails] {
114 let ids: [UInt64] = self.getIDsForAddress(address: address)
115 let vaults: [LockedVaultDetails] = []
116 for id in ids {
117 vaults.append(self.lockedVaults[id]?.details!)
118 }
119 return vaults
120 }
121
122 init() {
123 self.lockedVaults <- {}
124 self.addressMap = {}
125 self.additions <- {}
126 }
127 }
128
129 access(all) fun createManager(): @Manager {
130 return <- create Manager()
131 }
132}