Skip to content

Commit

Permalink
chore: update NftMetadata & TokenMetadata examples
Browse files Browse the repository at this point in the history
Signed-off-by: Ricky Saechao <[email protected]>
  • Loading branch information
RickyLB committed Apr 23, 2024
1 parent f3ace20 commit a6de34f
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 167 deletions.
199 changes: 199 additions & 0 deletions Examples/NftUpdateMetadata/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
* ‌
* Hedera Swift SDK
*
* Copyright (C) 2022 - 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import Foundation
import Hedera
import SwiftDotenv

@main
internal enum Program {

private static let metadataKey: PrivateKey = PrivateKey.generateEd25519()
private static let initialMetadata: Data = Data([1])
private static let newMetadata: Data = Data([1, 2])

internal static func main() async throws {
let env = try Dotenv.load()
let client = try Client.forName(env.networkName)

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
client.setOperator(env.operatorAccountId, env.operatorKey)

// Demonstrate with an immutable token (without admin key)
try await updateNftsMetadata(client, env, try getMutableTokenCreateTransaction(client, env))

// Demonstrate with an immutable token (without admin key)
try await updateNftsMetadata(client, env, try getImmutableTokenCreateTransaction(client, env))

}

internal static func updateNftsMetadata(
_ client: Client, _ env: Environment, _ tokenCreateTransaction: TokenCreateTransaction
) async throws {
let tokenCreateResponse = try await tokenCreateTransaction.sign(env.operatorKey).execute(client)
let tokenCreateReceipt = try await tokenCreateResponse.getReceipt(client)

print("Status of token create transaction: \(tokenCreateReceipt.status)")

let tokenId = tokenCreateReceipt.tokenId!
print("Token id: \(tokenId)")

let tokenInfo = try await TokenInfoQuery()
.tokenId(tokenId)
.execute(client)

print("Token metadata key: \(tokenInfo.metadataKey!)")

let tokenMintTransaction = TokenMintTransaction()
.tokenId(tokenId)
.metadata([initialMetadata])

_ = tokenMintTransaction.metadata.map {
print("Set metadata: \($0.bytes)")
}

let tokenMintReceipt = try await tokenMintTransaction.execute(client).getReceipt(client)

print("Status of token mint transaction: \(tokenMintReceipt.status)")

let nftSerials = tokenMintReceipt.serials!

let accountCreateTransaction = try await AccountCreateTransaction()
.key(.single(env.operatorKey.publicKey))
.maxAutomaticTokenAssociations(10)
.execute(client)

// Create an account to send the NFT to
let newAccountId = try await accountCreateTransaction.getReceipt(client).accountId!

// Associate the NFT to the account only if the account does not have any automatic token association slots open. When we created the account in the previous step we set automatic token associations to 10 so I should have 10 slots open to receive a token
// _ = try await TokenAssociateTransaction()
// .accountId(newAccountId)
// .tokenIds([tokenId])
// .freezeWith(client)
// .sign(env.operatorKey)
// .execute(client)
// .getReceipt(client)

// Transfer the Nft to the new account
_ = try await TransferTransaction()
.nftTransfer(tokenId.nft(nftSerials.first!), env.operatorAccountId, newAccountId)
.execute(client)

// Update metadata of Nft
let tokenUpdateNftsTransaction = try TokenUpdateNftsTransaction()
.tokenId(tokenId)
.serials(nftSerials)
.metadata(newMetadata)
.freezeWith(client)

print("Updated metadata: \(tokenUpdateNftsTransaction.metadata.bytes)")

// Get receipt for update nfts metadata transaction
let tokenUpdateNftsReceipt = try await tokenUpdateNftsTransaction.sign(metadataKey).execute(client).getReceipt(
client)

print("Status of token update nfts metadata transaction: \(tokenUpdateNftsReceipt.status)")

// Check that metadata for the NFT was updated correctly
let metadataList = try await getMetadataList(client, tokenId, nftSerials)

print("Metadata after update: \(metadataList)")
}

internal static func getMutableTokenCreateTransaction(_ client: Client, _ env: Environment) throws
-> TokenCreateTransaction
{
print("Creating a mutable token")

return try TokenCreateTransaction()
.name("Mutable")
.symbol("MUT")
.tokenType(TokenType.nonFungibleUnique)
.treasuryAccountId(env.operatorAccountId)
.adminKey(.single(env.operatorKey.publicKey))
.supplyKey(.single(env.operatorKey.publicKey))
.metadataKey(.single(metadataKey.publicKey))
.expirationTime(Timestamp.now + .hours(2))
.freezeWith(client)
}

internal static func getImmutableTokenCreateTransaction(_ client: Client, _ env: Environment) throws
-> TokenCreateTransaction
{
print("Creating a immutable token")

return try TokenCreateTransaction()
.name("Immutable")
.symbol("IMMUT")
.tokenType(TokenType.nonFungibleUnique)
.treasuryAccountId(env.operatorAccountId)
.supplyKey(.single(env.operatorKey.publicKey))
.metadataKey(.single(metadataKey.publicKey))
.expirationTime(Timestamp.now + .hours(2))
.freezeWith(client)
}
}

func getMetadataList(_ client: Client, _ tokenId: TokenId, _ serials: [UInt64]) async throws -> [Data] {
let metadataList: [Data] = try await withThrowingTaskGroup(
of: Data.self,
body: { group in
var results = [Data]()

// Iterate over serials, launching a new task for each
for serial in serials {
group.addTask {
let nftId = NftId(tokenId: tokenId, serial: UInt64(serial))
// Execute the query and return the result
return try await TokenNftInfoQuery().nftId(nftId).execute(client).metadata
}
}

// Collect results from all tasks
for try await result in group {
results.append(result)
}

return results
})

return metadataList
}

extension Environment {
/// Account ID for the operator to use in this example.
internal var operatorAccountId: AccountId {
AccountId(self["OPERATOR_ID"]!.stringValue)!
}

/// Private key for the operator to use in this example.
internal var operatorKey: PrivateKey {
PrivateKey(self["OPERATOR_KEY"]!.stringValue)!
}

/// The name of the hedera network this example should be ran against.
///
/// Testnet by default.
internal var networkName: String {
self["HEDERA_NETWORK"]?.stringValue ?? "testnet"
}
}
150 changes: 150 additions & 0 deletions Examples/TokenUpdateMetadata/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* ‌
* Hedera Swift SDK
*
* Copyright (C) 2022 - 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import Foundation
import Hedera
import SwiftDotenv

@main
internal enum Program {

private static let metadataKey: PrivateKey = PrivateKey.generateEd25519()
private static let initialMetadata: Data = Data([1])
private static let newMetadata: Data = Data([1, 2])

internal static func main() async throws {
let env = try Dotenv.load()
let client = try Client.forName(env.networkName)

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
client.setOperator(env.operatorAccountId, env.operatorKey)

// Demonstrate with an immutable token (without admin key)
try await getMutableTokenCreateTransaction(client, env)

// Demonstrate with an immutable token (without admin key)
try await getImmutableTokenCreateTransaction(client, env)

}

internal static func getMutableTokenCreateTransaction(_ client: Client, _ env: Environment) async throws {
print("Creating a mutable token")

let tokenId = try await TokenCreateTransaction()
.name("Mutable")
.symbol("MUT")
.tokenType(TokenType.fungibleCommon)
.decimals(3)
.initialSupply(100000)
.treasuryAccountId(env.operatorAccountId)
.adminKey(.single(env.operatorKey.publicKey))
.metadata(initialMetadata)
.expirationTime(Timestamp.now + .hours(2))
.execute(client)
.getReceipt(client)
.tokenId!

print("Created a mutable token: \(tokenId)")

let tokenInfoAfterCreation = try await TokenInfoQuery()
.tokenId(tokenId)
.execute(client)

print("Mutable token's metadata after creation: \(tokenInfoAfterCreation.metadata.bytes)")

// Update token's metadata
_ = try await TokenUpdateTransaction()
.tokenId(tokenId)
.metadata(newMetadata)
.execute(client)
.getReceipt(client)

let tokenInfoAfterMetadataUpdate = try await TokenInfoQuery()
.tokenId(tokenId)
.execute(client)

// check that metadata was updated correctly
print("Mutable token's metadata after update: \(tokenInfoAfterMetadataUpdate.metadata.bytes)")
}

internal static func getImmutableTokenCreateTransaction(_ client: Client, _ env: Environment) async throws {
print("Creating a immutable token")

let tokenId = try await TokenCreateTransaction()
.name("Immutable")
.symbol("IMMUT")
.tokenType(TokenType.fungibleCommon)
.treasuryAccountId(env.operatorAccountId)
.metadataKey(.single(metadataKey.publicKey))
.expirationTime(Timestamp.now + .hours(2))
.metadataKey(.single(metadataKey.publicKey))
.metadata(initialMetadata)
.freezeWith(client)
.sign(env.operatorKey)
.execute(client)
.getReceipt(client)
.tokenId!

print("Created a immutable token: \(tokenId)")

// check that metadata was set correctly
let tokenInfoAfterCreation = try await TokenInfoQuery()
.tokenId(tokenId)
.execute(client)

print("Immutable token's metadata after creation: \(tokenInfoAfterCreation.metadata.bytes)")

// Update token's metadata
_ = try await TokenUpdateTransaction()
.tokenId(tokenId)
.metadata(newMetadata)
.freezeWith(client)
.sign(metadataKey)
.execute(client)
.getReceipt(client)

let tokenInfoAfterMetadataUpdate = try await TokenInfoQuery()
.tokenId(tokenId)
.execute(client)

// check that metadata was updated correctly
print("Immutable token's metadata after update: \(tokenInfoAfterMetadataUpdate.metadata.bytes)")
}
}

extension Environment {
/// Account ID for the operator to use in this example.
internal var operatorAccountId: AccountId {
AccountId(self["OPERATOR_ID"]!.stringValue)!
}

/// Private key for the operator to use in this example.
internal var operatorKey: PrivateKey {
PrivateKey(self["OPERATOR_KEY"]!.stringValue)!
}

/// The name of the hedera network this example should be ran against.
///
/// Testnet by default.
internal var networkName: String {
self["HEDERA_NETWORK"]?.stringValue ?? "testnet"
}
}
Loading

0 comments on commit a6de34f

Please sign in to comment.