github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/examples/token_airdrop/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/hashgraph/hedera-sdk-go/v2" 8 ) 9 10 /** 11 * @summary HIP-904 https://hips.hedera.com/hip/hip-904 12 * @description Airdrop fungible and non fungible tokens to an account 13 */ 14 func main() { 15 16 var client *hedera.Client 17 var err error 18 19 // Retrieving network type from environment variable HEDERA_NETWORK 20 client, err = hedera.ClientForName(os.Getenv("HEDERA_NETWORK")) 21 if err != nil { 22 panic(fmt.Sprintf("%v : error creating client", err)) 23 } 24 25 // Retrieving operator ID from environment variable OPERATOR_ID 26 operatorAccountID, err := hedera.AccountIDFromString(os.Getenv("OPERATOR_ID")) 27 if err != nil { 28 panic(fmt.Sprintf("%v : error converting string to AccountID", err)) 29 } 30 31 // Retrieving operator key from environment variable OPERATOR_KEY 32 operatorKey, err := hedera.PrivateKeyFromString(os.Getenv("OPERATOR_KEY")) 33 if err != nil { 34 panic(fmt.Sprintf("%v : error converting string to PrivateKey", err)) 35 } 36 37 // Setting the client operator ID and key 38 client.SetOperator(operatorAccountID, operatorKey) 39 40 fmt.Println("Example Start!") 41 42 /* 43 * Step 1: 44 * Create 4 accounts 45 */ 46 privateKey1, _ := hedera.PrivateKeyGenerateEd25519() 47 accountCreateResp, err := hedera.NewAccountCreateTransaction(). 48 SetKey(privateKey1). 49 SetInitialBalance(hedera.NewHbar(10)). 50 SetMaxAutomaticTokenAssociations(-1). 51 Execute(client) 52 if err != nil { 53 panic(fmt.Sprintf("%v error creating account", err)) 54 } 55 receipt, err := accountCreateResp.GetReceipt(client) 56 if err != nil { 57 panic(fmt.Sprintf("%v error creating account", err)) 58 } 59 alice := receipt.AccountID 60 61 privateKey2, _ := hedera.PrivateKeyGenerateEd25519() 62 accountCreateResp, err = hedera.NewAccountCreateTransaction(). 63 SetKey(privateKey2). 64 SetInitialBalance(hedera.NewHbar(10)). 65 SetMaxAutomaticTokenAssociations(1). 66 Execute(client) 67 if err != nil { 68 panic(fmt.Sprintf("%v error creating account", err)) 69 } 70 receipt, err = accountCreateResp.GetReceipt(client) 71 if err != nil { 72 panic(fmt.Sprintf("%v error creating account", err)) 73 } 74 bob := receipt.AccountID 75 76 privateKey3, _ := hedera.PrivateKeyGenerateEd25519() 77 accountCreateResp, err = hedera.NewAccountCreateTransaction(). 78 SetKey(privateKey3). 79 SetInitialBalance(hedera.NewHbar(10)). 80 SetMaxAutomaticTokenAssociations(0). 81 Execute(client) 82 if err != nil { 83 panic(fmt.Sprintf("%v error creating account", err)) 84 } 85 receipt, err = accountCreateResp.GetReceipt(client) 86 if err != nil { 87 panic(fmt.Sprintf("%v error creating account", err)) 88 } 89 carol := receipt.AccountID 90 91 treasuryKey, _ := hedera.PrivateKeyGenerateEd25519() 92 accountCreateResp, err = hedera.NewAccountCreateTransaction(). 93 SetKey(treasuryKey). 94 SetInitialBalance(hedera.NewHbar(10)). 95 Execute(client) 96 if err != nil { 97 panic(fmt.Sprintf("%v error creating account", err)) 98 } 99 100 receipt, err = accountCreateResp.GetReceipt(client) 101 if err != nil { 102 panic(fmt.Sprintf("%v error creating account", err)) 103 } 104 treasury := receipt.AccountID 105 106 /* 107 * Step 2: 108 * Create FT and NFT and mint 109 */ 110 tokenCreateTxn, _ := hedera.NewTokenCreateTransaction(). 111 SetTokenName("Fungible Token"). 112 SetTokenSymbol("TFT"). 113 SetTokenMemo("Example memo"). 114 SetDecimals(3). 115 SetInitialSupply(1000). 116 SetMaxSupply(1000). 117 SetTreasuryAccountID(*treasury). 118 SetSupplyType(hedera.TokenSupplyTypeFinite). 119 SetAdminKey(operatorKey). 120 SetFreezeKey(operatorKey). 121 SetSupplyKey(operatorKey). 122 SetMetadataKey(operatorKey). 123 SetPauseKey(operatorKey). 124 FreezeWith(client) 125 126 tokenCreateResp, err := tokenCreateTxn.Sign(treasuryKey).Execute(client) 127 if err != nil { 128 panic(fmt.Sprintf("%v error creating token", err)) 129 } 130 131 receipt, err = tokenCreateResp.GetReceipt(client) 132 if err != nil { 133 panic(fmt.Sprintf("%v : error creating token", err)) 134 } 135 tokenID := receipt.TokenID 136 137 nftCreateTransaction, _ := hedera.NewTokenCreateTransaction(). 138 SetTokenName("Example NFT"). 139 SetTokenSymbol("ENFT"). 140 SetTokenType(hedera.TokenTypeNonFungibleUnique). 141 SetDecimals(0). 142 SetInitialSupply(0). 143 SetMaxSupply(10). 144 SetTreasuryAccountID(*treasury). 145 SetSupplyType(hedera.TokenSupplyTypeFinite). 146 SetAdminKey(operatorKey). 147 SetFreezeKey(operatorKey). 148 SetSupplyKey(operatorKey). 149 FreezeWith(client) 150 tokenCreateResp, err = nftCreateTransaction.Sign(treasuryKey).Execute(client) 151 if err != nil { 152 panic(fmt.Sprintf("%v : error creating token", err)) 153 } 154 nftCreateReceipt, err := tokenCreateResp.GetReceipt(client) 155 if err != nil { 156 panic(fmt.Sprintf("%v : error creating token", err)) 157 } 158 nftID := *nftCreateReceipt.TokenID 159 var initialMetadataList = [][]byte{{2, 1}, {1, 2}, {1, 5}} 160 161 mintTransaction, _ := hedera.NewTokenMintTransaction(). 162 SetTokenID(nftID). 163 SetMetadatas(initialMetadataList). 164 FreezeWith(client) 165 166 mintTransactionSubmit, err := mintTransaction.Sign(operatorKey).Execute(client) 167 if err != nil { 168 panic(fmt.Sprintf("%v : error minting NFT", err)) 169 } 170 receipt, err = mintTransactionSubmit.GetReceipt(client) 171 if err != nil { 172 panic(fmt.Sprintf("%v : error minting NFT", err)) 173 } 174 175 /* 176 * Step 3: 177 * Airdrop fungible tokens to all 3 accounts 178 */ 179 180 airdropTx, _ := hedera.NewTokenAirdropTransaction(). 181 AddTokenTransfer(*tokenID, *alice, 100). 182 AddTokenTransfer(*tokenID, *bob, 100). 183 AddTokenTransfer(*tokenID, *carol, 100). 184 AddTokenTransfer(*tokenID, *treasury, -300). 185 FreezeWith(client) 186 airdropResponse, err := airdropTx.Sign(treasuryKey).Execute(client) 187 if err != nil { 188 panic(fmt.Sprintf("%v : error airdropping tokens", err)) 189 } 190 record, err := airdropResponse.GetRecord(client) 191 if err != nil { 192 panic(fmt.Sprintf("%v : error airdropping tokens", err)) 193 } 194 195 fmt.Println("Pending airdrops length: ", len(record.PendingAirdropRecords)) 196 fmt.Println("Pending airdrops: ", record.PendingAirdropRecords[0].String()) 197 198 /* 199 * Step 5: 200 * Query to verify alice and bob received the airdrops and carol did not 201 */ 202 aliceBalance, _ := hedera.NewAccountBalanceQuery(). 203 SetAccountID(*alice). 204 Execute(client) 205 206 bobBalance, _ := hedera.NewAccountBalanceQuery(). 207 SetAccountID(*alice). 208 Execute(client) 209 carolBalance, _ := hedera.NewAccountBalanceQuery(). 210 SetAccountID(*alice). 211 Execute(client) 212 213 fmt.Println("Alice ft balance after airdrop: ", aliceBalance.Tokens.Get(*tokenID)) 214 fmt.Println("Bob ft balance after airdrop: ", bobBalance.Tokens.Get(*tokenID)) 215 fmt.Println("Carol ft balance after airdrop: ", carolBalance.Tokens.Get(*tokenID)) 216 217 /* 218 * Step 6: 219 * Claim the airdrop for carol 220 */ 221 fmt.Println("Claiming ft with carol") 222 223 claimTx, _ := hedera.NewTokenClaimAirdropTransaction(). 224 AddPendingAirdropId(record.PendingAirdropRecords[0].GetPendingAirdropId()). 225 FreezeWith(client) 226 227 _, err = claimTx.Sign(privateKey3).Execute(client) 228 if err != nil { 229 panic(fmt.Sprintf("%v : error claiming tokens", err)) 230 } 231 carolBalance, _ = hedera.NewAccountBalanceQuery(). 232 SetAccountID(*alice). 233 Execute(client) 234 fmt.Println("Carol ft balance after claim: ", carolBalance.Tokens.Get(*tokenID)) 235 236 /* 237 * Step 7: 238 * Airdrop the NFTs to all three accounts 239 */ 240 241 airdropTx, _ = hedera.NewTokenAirdropTransaction(). 242 AddNftTransfer(nftID.Nft(1), *treasury, *alice). 243 AddNftTransfer(nftID.Nft(2), *treasury, *bob). 244 AddNftTransfer(nftID.Nft(3), *treasury, *carol). 245 FreezeWith(client) 246 airdropResponse, err = airdropTx.Sign(treasuryKey).Execute(client) 247 if err != nil { 248 panic(fmt.Sprintf("%v : error airdropping tokens", err)) 249 } 250 record, err = airdropResponse.GetRecord(client) 251 if err != nil { 252 panic(fmt.Sprintf("%v : error airdropping tokens", err)) 253 } 254 255 /* 256 * Step 8: 257 * Get the transaction record and verify two pending airdrops (for bob & carol) 258 */ 259 260 fmt.Println("Pending airdrops length: ", len(record.PendingAirdropRecords)) 261 fmt.Println("Pending airdrops for Bob: ", record.PendingAirdropRecords[0].String()) 262 fmt.Println("Pending airdrops for Carol: ", record.PendingAirdropRecords[1].String()) 263 264 /* 265 * Step 9: 266 * Query to verify alice received the airdrop and bob and carol did not 267 */ 268 269 aliceBalance, _ = hedera.NewAccountBalanceQuery(). 270 SetAccountID(*alice). 271 Execute(client) 272 273 bobBalance, _ = hedera.NewAccountBalanceQuery(). 274 SetAccountID(*alice). 275 Execute(client) 276 carolBalance, _ = hedera.NewAccountBalanceQuery(). 277 SetAccountID(*alice). 278 Execute(client) 279 280 fmt.Println("Alice nft balance after airdrop: ", aliceBalance.Tokens.Get(nftID)) 281 fmt.Println("Bob nft balance after airdrop: ", bobBalance.Tokens.Get(nftID)) 282 fmt.Println("Carol nft balance after airdrop: ", carolBalance.Tokens.Get(nftID)) 283 284 /* 285 * Step 10: 286 * Claim the airdrop for bob 287 */ 288 fmt.Println("Claiming nft with Bob") 289 claimTx, _ = hedera.NewTokenClaimAirdropTransaction(). 290 AddPendingAirdropId(record.PendingAirdropRecords[0].GetPendingAirdropId()). 291 FreezeWith(client) 292 293 claimResp, err := claimTx.Sign(privateKey2).Execute(client) 294 if err != nil { 295 panic(fmt.Sprintf("%v : error claiming tokens", err)) 296 } 297 _, err = claimResp.GetReceipt(client) 298 if err != nil { 299 panic(fmt.Sprintf("%v : error claiming tokens", err)) 300 } 301 bobBalance, _ = hedera.NewAccountBalanceQuery(). 302 SetAccountID(*bob). 303 Execute(client) 304 fmt.Println("Bob nft balance after claim: ", bobBalance.Tokens.Get(nftID)) 305 306 /* 307 * Step 11: 308 * Cancel the airdrop for carol 309 */ 310 fmt.Println("Canceling nft with Carol") 311 cancelTx, _ := hedera.NewTokenCancelAirdropTransaction(). 312 AddPendingAirdropId(record.PendingAirdropRecords[1].GetPendingAirdropId()). 313 FreezeWith(client) 314 315 cancelResp, err := cancelTx.Sign(treasuryKey).Execute(client) 316 if err != nil { 317 panic(fmt.Sprintf("%v : error canceling tokens", err)) 318 } 319 _, err = cancelResp.GetReceipt(client) 320 if err != nil { 321 panic(fmt.Sprintf("%v : error canceling tokens", err)) 322 } 323 carolBalance, _ = hedera.NewAccountBalanceQuery(). 324 SetAccountID(*carol). 325 Execute(client) 326 fmt.Println("Carol nft balance after cancel: ", carolBalance.Tokens.Get(nftID)) 327 328 /* 329 * Step 12: 330 * Reject the NFT for bob 331 */ 332 fmt.Println("Rejecting nft with Bob") 333 334 rejectTxn, _ := hedera.NewTokenRejectTransaction(). 335 AddNftID(nftID.Nft(2)). 336 SetOwnerID(*bob). 337 FreezeWith(client) 338 339 rejectResp, err := rejectTxn.Sign(privateKey2).Execute(client) 340 if err != nil { 341 panic(fmt.Sprintf("%v : error rejecting tokens", err)) 342 } 343 _, err = rejectResp.GetReceipt(client) 344 if err != nil { 345 panic(fmt.Sprintf("%v : error rejecting tokens", err)) 346 } 347 348 /* 349 * Step 13: 350 * Query to verify bob no longer has the NFT 351 */ 352 bobBalance, _ = hedera.NewAccountBalanceQuery(). 353 SetAccountID(*bob). 354 Execute(client) 355 fmt.Println("Bob nft balance after reject: ", bobBalance.Tokens.Get(nftID)) 356 357 /* 358 * Step 13: 359 * Query to verify the NFT was returned to the Treasury 360 */ 361 treasuryBalance, _ := hedera.NewAccountBalanceQuery(). 362 SetAccountID(*treasury). 363 Execute(client) 364 fmt.Println("Treasury nft balance after reject: ", treasuryBalance.Tokens.Get(nftID)) 365 366 /* 367 * Step 14: 368 * Reject the fungible tokens for Carol 369 */ 370 371 rejectTxn, _ = hedera.NewTokenRejectTransaction(). 372 AddTokenID(*tokenID). 373 SetOwnerID(*carol). 374 FreezeWith(client) 375 376 rejectResp, err = rejectTxn.Sign(privateKey3).Execute(client) 377 if err != nil { 378 panic(fmt.Sprintf("%v : error rejecting tokens", err)) 379 } 380 _, err = rejectResp.GetReceipt(client) 381 if err != nil { 382 panic(fmt.Sprintf("%v : error rejecting tokens", err)) 383 } 384 385 /* 386 * Step 14: 387 * Query to verify carol no longer has the fungible tokens 388 */ 389 carolBalance, _ = hedera.NewAccountBalanceQuery(). 390 SetAccountID(*alice). 391 Execute(client) 392 fmt.Println("Carol ft balance after claim: ", carolBalance.Tokens.Get(*tokenID)) 393 394 /* 395 * Step 15: 396 * Query to verify Treasury received the rejected fungible tokens 397 */ 398 treasuryBalance, _ = hedera.NewAccountBalanceQuery(). 399 SetAccountID(*treasury). 400 Execute(client) 401 fmt.Println("Treasury ft balance after reject: ", treasuryBalance.Tokens.Get(*tokenID)) 402 403 /* 404 * Clean up: 405 */ 406 client.Close() 407 408 fmt.Println("Example Complete!") 409 410 }