Smart Contract
FindAirdropper
A.097bafa4e0b48eef.FindAirdropper
1import NonFungibleToken from 0x1d7e57aa55817448
2import FIND from 0x097bafa4e0b48eef
3import FungibleToken from 0xf233dcee88fe0abe
4import FlowToken from 0x1654653399040a61
5import FindMarket from 0x097bafa4e0b48eef
6import FindViews from 0x097bafa4e0b48eef
7import FindLostAndFoundWrapper from 0x097bafa4e0b48eef
8import MetadataViews from 0x1d7e57aa55817448
9
10access(all) contract FindAirdropper {
11 // Events
12 access(all) event Airdropped(from: Address ,fromName: String?, to: Address, toName: String?,uuid: UInt64, nftInfo: FindMarket.NFTInfo, context: {String : String}, remark: String?)
13 access(all) event AirdroppedToLostAndFound(from: Address, fromName: String? , to: Address, toName: String?, uuid: UInt64, nftInfo: FindMarket.NFTInfo, context: {String : String}, remark: String?, ticketID: UInt64)
14 access(all) event AirdropFailed(from: Address, fromName: String? , to: Address, toName: String?, uuid: UInt64, id: UInt64, type: String, context: {String : String}, reason: String)
15
16 // The normal way of airdrop. If the user didn't init account, they cannot receive it
17 access(all) fun safeAirdrop(pointer: FindViews.AuthNFTPointer, receiver: Address, path: PublicPath, context: {String : String}, deepValidation: Bool) {
18 let toName = FIND.reverseLookup(receiver)
19 let from = pointer.owner()
20 let fromName = FIND.reverseLookup(from)
21 if deepValidation && !pointer.valid() {
22 emit AirdropFailed(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, id: pointer.id, type: pointer.itemType.identifier, context: context, reason: "Invalid NFT Pointer")
23 return
24 }
25
26 let vr = pointer.getViewResolver()
27 let nftInfo = FindMarket.NFTInfo(vr, id: pointer.id, detail: true)
28
29 let receiverCap = getAccount(receiver).capabilities.get<&{NonFungibleToken.Receiver}>(path)
30 // calculate the required storage and check sufficient balance
31 let senderStorageBeforeSend = getAccount(from).storage.used
32
33 let item <- pointer.withdraw()
34
35 let requiredStorage = senderStorageBeforeSend - getAccount(from).storage.used
36 let receiverAvailableStorage = getAccount(receiver).storage.capacity - getAccount(receiver).storage.used
37 // If requiredStorage > receiverAvailableStorage, deposit will not be successful, we will emit fail event and deposit back to the sender's collection
38 if receiverAvailableStorage < requiredStorage {
39 emit AirdropFailed(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, id: pointer.id, type: pointer.itemType.identifier, context: context, reason: "Insufficient User Storage")
40 pointer.deposit(<- item)
41 return
42 }
43
44 if receiverCap.check() {
45 emit Airdropped(from: from , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: nil)
46 receiverCap.borrow()!.deposit(token: <- item)
47 return
48 } else {
49 let collectionPublic = getAccount(receiver).capabilities.borrow<&{NonFungibleToken.Collection}>(path)
50 if collectionPublic !=nil {
51
52 let from = pointer.owner()
53 emit Airdropped(from: from , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: "Receiver Not Linked")
54
55 collectionPublic!.deposit(token: <- item)
56 return
57 }
58 }
59
60 emit AirdropFailed(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, id: pointer.id, type: pointer.itemType.identifier, context: context, reason: "Invalid Receiver Capability")
61 pointer.deposit(<- item)
62 }
63
64 access(all) fun forcedAirdrop(pointer: FindViews.AuthNFTPointer, receiver: Address, path: PublicPath, context: {String : String}, storagePayment: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}, flowTokenRepayment: Capability<&FlowToken.Vault>, deepValidation: Bool) {
65
66 let toName = FIND.reverseLookup(receiver)
67 let from = pointer.owner()
68 let fromName = FIND.reverseLookup(from)
69
70 if deepValidation && !pointer.valid() {
71 emit AirdropFailed(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, id: pointer.id, type: pointer.itemType.identifier, context: context, reason: "Invalid NFT Pointer")
72 return
73 }
74
75 let vr = pointer.getViewResolver()
76 let nftInfo = FindMarket.NFTInfo(vr, id: pointer.id, detail: true)
77
78 // use LostAndFound for dropping
79 let ticketID = FindLostAndFoundWrapper.depositNFT(
80 receiver: receiver,
81 collectionPublicPath: path,
82 item: pointer,
83 memo: context["message"],
84 storagePayment: storagePayment,
85 flowTokenRepayment: flowTokenRepayment,
86 subsidizeReceiverStorage: false
87 )
88
89 if ticketID == nil {
90 emit Airdropped(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: nil)
91 return
92 }
93 emit AirdroppedToLostAndFound(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: nil, ticketID: ticketID!)
94 }
95
96 access(all) fun subsidizedAirdrop(pointer: FindViews.AuthNFTPointer, receiver: Address, path: PublicPath, context: {String : String}, storagePayment: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}, flowTokenRepayment: Capability<&FlowToken.Vault>, deepValidation: Bool) {
97
98 let toName = FIND.reverseLookup(receiver)
99 let from = pointer.owner()
100 let fromName = FIND.reverseLookup(from)
101
102 if deepValidation && !pointer.valid() {
103 emit AirdropFailed(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, id: pointer.id, type: pointer.itemType.identifier, context: context, reason: "Invalid NFT Pointer")
104 return
105 }
106
107 let vr = pointer.getViewResolver()
108 let nftInfo = FindMarket.NFTInfo(vr, id: pointer.id, detail: true)
109
110 let receiverCap = getAccount(receiver).capabilities.get<&{NonFungibleToken.Receiver}>(path)
111
112 // use LostAndFound for dropping
113 let ticketID = FindLostAndFoundWrapper.depositNFT(
114 receiver: receiver,
115 collectionPublicPath: path,
116 item: pointer,
117 memo: context["message"],
118 storagePayment: storagePayment,
119 flowTokenRepayment: flowTokenRepayment,
120 subsidizeReceiverStorage: true
121 )
122
123 if ticketID == nil {
124 emit Airdropped(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: nil)
125 return
126 }
127 emit AirdroppedToLostAndFound(from: pointer.owner() , fromName: fromName, to: receiver, toName: toName, uuid: pointer.uuid, nftInfo: nftInfo, context: context, remark: nil, ticketID: ticketID!)
128 }
129}
130
131