github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/token_update_nfts_transaction_e2e_test.go (about) 1 //go:build all || e2e 2 // +build all e2e 3 4 package hedera 5 6 import ( 7 "reflect" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 /*- 15 * 16 * Hedera Go SDK 17 * 18 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 * 32 */ 33 34 func TestTokenUpdateNftsUpdatesMetadata(t *testing.T) { 35 env := NewIntegrationTestEnv(t) 36 37 // create supply key 38 supplyKey, err := PrivateKeyGenerateEd25519() 39 require.NoError(t, err) 40 supplyPublicKey := supplyKey.PublicKey() 41 42 // create metadata key 43 metadataKey, err := PrivateKeyGenerateEd25519() 44 require.NoError(t, err) 45 metadataPublicKey := metadataKey.PublicKey() 46 47 nftCount := 4 48 // create metadata list for all NFTs 49 mintMetadata := generateNftMetadata([]byte{4, 2, 0}, nftCount) 50 updatedMetadata := []byte{6, 9} 51 // create updated metadata list for all NFTs 52 updatedMetadataList := generateNftMetadata(updatedMetadata, nftCount/2) 53 54 // create token with metadata key 55 tokenID := createTokenWithMetadataKey(t, &env, &metadataPublicKey, &supplyPublicKey) 56 57 // mint tokens using the metadata list 58 tokenMintTx, _ := NewTokenMintTransaction(). 59 SetMetadatas(mintMetadata). 60 SetTokenID(tokenID). 61 FreezeWith(env.Client) 62 tx, err := tokenMintTx.Sign(supplyKey).Execute(env.Client) 63 require.NoError(t, err) 64 receipt, err := tx.GetReceipt(env.Client) 65 require.NoError(t, err) 66 nftSerials := receipt.SerialNumbers 67 68 // verify the metadata is set in the new tokens 69 metadataListAfterMint := getMetadataList(t, &env, tokenID, nftSerials) 70 71 assert.True(t, reflect.DeepEqual(metadataListAfterMint, mintMetadata), "metadata after minting should match initial metadata") 72 73 // update nft metadata for half of the NFTs 74 _, err = updateNftMetadata(t, &env, tokenID, nftSerials[:nftCount/2], updatedMetadata, &metadataKey) 75 require.NoError(t, err) 76 77 // verify the metadata is updated 78 metadataListAfterUpdate := getMetadataList(t, &env, tokenID, nftSerials[:nftCount/2]) 79 assert.True(t, reflect.DeepEqual(metadataListAfterUpdate, updatedMetadataList), "updated metadata should match expected updated metadata") 80 81 // verify the remaining NFTs' metadata is unchanged 82 metadataList := getMetadataList(t, &env, tokenID, nftSerials[nftCount/2:]) 83 84 assert.True(t, reflect.DeepEqual(metadataList, mintMetadata[nftCount/2:]), "remaining NFTs' metadata should remain unchanged") 85 } 86 87 func TestCanUpdateEmptyNFTMetadata(t *testing.T) { 88 env := NewIntegrationTestEnv(t) 89 90 // create supply key 91 supplyKey, err := PrivateKeyGenerateEd25519() 92 require.NoError(t, err) 93 supplyPublicKey := supplyKey.PublicKey() 94 95 // Generate metadata key 96 metadataKey, err := PrivateKeyGenerateEd25519() 97 require.NoError(t, err) 98 metadataPublicKey := metadataKey.PublicKey() 99 100 nftCount := 4 101 mintMetadata := generateNftMetadata([]byte{4, 2, 0}, nftCount) 102 updatedMetadata := make([]byte, 0) 103 updatedMetadataList := make([][]byte, 4) 104 105 // Create a token with a metadata key 106 tokenID := createTokenWithMetadataKey(t, &env, &metadataPublicKey, &supplyPublicKey) 107 108 // Mint tokens 109 tokenMintTx, _ := NewTokenMintTransaction(). 110 SetMetadatas(mintMetadata). 111 SetTokenID(tokenID). 112 FreezeWith(env.Client) 113 tx, err := tokenMintTx.Sign(supplyKey).Execute(env.Client) 114 require.NoError(t, err) 115 receipt, err := tx.GetReceipt(env.Client) 116 require.NoError(t, err) 117 nftSerials := receipt.SerialNumbers 118 119 metadataListAfterMint := getMetadataList(t, &env, tokenID, nftSerials) 120 assert.Equal(t, mintMetadata, metadataListAfterMint, "metadata after minting should match initial metadata") 121 122 // Update metadata for all NFTs 123 _, err = updateNftMetadata(t, &env, tokenID, nftSerials, updatedMetadata, &metadataKey) 124 require.NoError(t, err) 125 126 // Verify updated metadata for NFTs 127 metadataListAfterUpdate := getMetadataList(t, &env, tokenID, nftSerials) 128 assert.Equal(t, updatedMetadataList, metadataListAfterUpdate, "updated metadata should match expected updated metadata") 129 } 130 131 func TestCannotUpdateNFTMetadataWhenKeyIsNotSet(t *testing.T) { 132 env := NewIntegrationTestEnv(t) 133 134 // create supply key 135 supplyKey, err := PrivateKeyGenerateEd25519() 136 require.NoError(t, err) 137 supplyPublicKey := supplyKey.PublicKey() 138 139 // Generate metadata key 140 metadataKey, err := PrivateKeyGenerateEd25519() 141 require.NoError(t, err) 142 143 nftCount := 4 144 mintMetadata := generateNftMetadata([]byte{4, 2, 0}, nftCount) 145 updatedMetadata := []byte{6, 9} 146 147 // Create a token without a metadata key 148 tokenID := createTokenWithMetadataKey(t, &env, nil, &supplyPublicKey) 149 150 // Mint tokens 151 tokenMintTx, _ := NewTokenMintTransaction(). 152 SetMetadatas(mintMetadata). 153 SetTokenID(tokenID). 154 FreezeWith(env.Client) 155 tx, err := tokenMintTx.Sign(supplyKey).Execute(env.Client) 156 require.NoError(t, err) 157 receipt, err := tx.GetReceipt(env.Client) 158 require.NoError(t, err) 159 nftSerials := receipt.SerialNumbers 160 161 metadataListAfterMint := getMetadataList(t, &env, tokenID, nftSerials) 162 assert.Equal(t, mintMetadata, metadataListAfterMint, "metadata after minting should match initial metadata") 163 164 // Update metadata for the first half of the NFTs 165 _, err = updateNftMetadata(t, &env, tokenID, nftSerials[:nftCount/2], updatedMetadata, &metadataKey) 166 require.Error(t, err) 167 } 168 169 func TestCannotUpdateNFTMetadataWhenTransactionIsNotSignedWithMetadataKey(t *testing.T) { 170 env := NewIntegrationTestEnv(t) 171 172 // create supply key 173 supplyKey, err := PrivateKeyGenerateEd25519() 174 require.NoError(t, err) 175 supplyPublicKey := supplyKey.PublicKey() 176 177 // Generate metadata key 178 metadataKey, err := PrivateKeyGenerateEd25519() 179 require.NoError(t, err) 180 metadataPublicKey := metadataKey.PublicKey() 181 182 nftCount := 4 183 mintMetadata := generateNftMetadata([]byte{4, 2, 0}, nftCount) 184 updatedMetadata := []byte{6, 9} 185 186 // Create a token with a metadata key 187 tokenID := createTokenWithMetadataKey(t, &env, &metadataPublicKey, &supplyPublicKey) 188 189 // Mint tokens 190 tokenMintTx, _ := NewTokenMintTransaction(). 191 SetMetadatas(mintMetadata). 192 SetTokenID(tokenID). 193 FreezeWith(env.Client) 194 tx, err := tokenMintTx.Sign(supplyKey).Execute(env.Client) 195 require.NoError(t, err) 196 receipt, err := tx.GetReceipt(env.Client) 197 require.NoError(t, err) 198 nftSerials := receipt.SerialNumbers 199 200 // Assert this will fail 201 _, err = updateNftMetadata(t, &env, tokenID, nftSerials, updatedMetadata, &env.OperatorKey) 202 require.Error(t, err) 203 204 _, err = updateNftMetadata(t, &env, tokenID, nftSerials, updatedMetadata, nil) 205 require.Error(t, err) 206 } 207 208 // Utility functions 209 func createTokenWithMetadataKey(t *testing.T, env *IntegrationTestEnv, metadataKey *PublicKey, supplyKey *PublicKey) TokenID { 210 var tokenCreateTx *TokenCreateTransaction 211 if metadataKey == nil { 212 tokenCreateTx = NewTokenCreateTransaction(). 213 SetNodeAccountIDs(env.NodeAccountIDs). 214 SetTokenName("ffff"). 215 SetTokenSymbol("F"). 216 SetTokenType(TokenTypeNonFungibleUnique). 217 SetTreasuryAccountID(env.Client.GetOperatorAccountID()). 218 SetAdminKey(env.Client.GetOperatorPublicKey()). 219 SetSupplyKey(supplyKey) 220 } else { 221 tokenCreateTx = NewTokenCreateTransaction(). 222 SetNodeAccountIDs(env.NodeAccountIDs). 223 SetTokenName("ffff"). 224 SetTokenSymbol("F"). 225 SetTokenType(TokenTypeNonFungibleUnique). 226 SetTreasuryAccountID(env.Client.GetOperatorAccountID()). 227 SetAdminKey(env.Client.GetOperatorPublicKey()). 228 SetSupplyKey(supplyKey). 229 SetMetadataKey(metadataKey) 230 } 231 232 tx, err := tokenCreateTx.Execute(env.Client) 233 require.NoError(t, err) 234 235 receipt, err := tx.GetReceipt(env.Client) 236 require.NoError(t, err) 237 238 return *receipt.TokenID 239 } 240 241 func updateNftMetadata(t *testing.T, env *IntegrationTestEnv, tokenID TokenID, serials []int64, updatedMetadata []byte, metadataKey *PrivateKey) (*TransactionReceipt, error) { 242 var tokenUpdateNftsTx *TokenUpdateNfts 243 if metadataKey == nil { 244 tokenUpdateNftsTx = NewTokenUpdateNftsTransaction(). 245 SetTokenID(tokenID). 246 SetSerialNumbers(serials). 247 SetMetadata(updatedMetadata) 248 } else { 249 frozenTx, err := NewTokenUpdateNftsTransaction(). 250 SetTokenID(tokenID). 251 SetSerialNumbers(serials). 252 SetMetadata(updatedMetadata). 253 FreezeWith(env.Client) 254 require.NoError(t, err) 255 256 tokenUpdateNftsTx = frozenTx.Sign(*metadataKey) 257 } 258 259 tx, err := tokenUpdateNftsTx.Execute(env.Client) 260 require.NoError(t, err) 261 262 receipt, err := tx.GetReceipt(env.Client) 263 264 return &receipt, err 265 } 266 267 func getMetadataList(t *testing.T, env *IntegrationTestEnv, tokenID TokenID, nftSerials []int64) [][]byte { 268 var metadataList [][]byte 269 270 for _, serial := range nftSerials { 271 nftID := NftID{ 272 TokenID: tokenID, 273 SerialNumber: serial, 274 } 275 276 tokenNftInfoQuery := NewTokenNftInfoQuery(). 277 SetNodeAccountIDs(env.NodeAccountIDs). 278 SetNftID(nftID) 279 280 nftInfo, err := tokenNftInfoQuery.Execute(env.Client) 281 require.NoError(t, err) 282 metadataList = append(metadataList, nftInfo[0].Metadata) 283 } 284 285 return metadataList 286 } 287 288 func generateNftMetadata(data []byte, count int) [][]byte { 289 var metadataList [][]byte 290 291 for i := 0; i < count; i++ { 292 metadataList = append(metadataList, data) 293 } 294 295 return metadataList 296 }