All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hedera.hashgraph.sdk.TokenCreateTransaction Maven / Gradle / Ivy

The newest version!
/*-
 *
 * Hedera Java SDK
 *
 * Copyright (C) 2020 - 2024 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.
 *
 */
package com.hedera.hashgraph.sdk;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.hedera.hashgraph.sdk.proto.SchedulableTransactionBody;
import com.hedera.hashgraph.sdk.proto.TokenCreateTransactionBody;
import com.hedera.hashgraph.sdk.proto.TokenServiceGrpc;
import com.hedera.hashgraph.sdk.proto.TransactionBody;
import com.hedera.hashgraph.sdk.proto.TransactionResponse;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.grpc.MethodDescriptor;
import java.time.Duration;
import java.time.Instant;

import javax.annotation.Nonnegative;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;

/**
 * Create a new fungible or non-fungible token (NFT) on the Hedera network.
 * After you submit the transaction to the Hedera network, you can obtain the
 * new token ID by requesting the receipt. Smart contracts cannot access or
 * transfer HTS tokens at this time.
 *
 * NFTs
 *
 * For non-fungible tokens, the token ID represents a NFT class. Once the token
 * is created, you will have to mint each NFT using the token mint operation.
 *
 * See Hedera Documentation
 */
public class TokenCreateTransaction extends Transaction {
    private List customFees = new ArrayList<>();
    /**
     * The account which will act as a treasury for the token. This account
     * will receive the specified initial supply and any additional tokens
     * that are minted.  If tokens are burned, the supply will be decreased
     * from the treasury account.
     */
    @Nullable
    private AccountId treasuryAccountId = null;
    /**
     * An account which will be automatically charged to renew the token's
     * expiration, at autoRenewPeriod interval. This key is required to
     * sign the transaction if present. This is not currently enabled.
     */
    @Nullable
    private AccountId autoRenewAccountId = null;
    /**
     * Set the publicly visible name of the token. The token name is specified
     * as a string of UTF-8 characters in Unicode. UTF-8 encoding of this
     * Unicode cannot contain the 0 byte (NUL). The token name is not unique.
     * Maximum of 100 characters.
     */
    private String tokenName = "";
    /**
     * The publicly visible token symbol. Set the publicly visible name of the
     * token. The token symbol is specified as a string of UTF-8 characters in
     * Unicode. UTF-8 encoding of this Unicode cannot contain the 0 byte (NUL).
     * The token symbol is not unique. Maximum of 100 characters.
     */
    private String tokenSymbol = "";
    /**
     * The number of decimal places a token is divisible by. This field can
     * never be changed.
     */
    private int decimals = 0;
    /**
     * Specifies the initial supply of fungible tokens to be put in
     * circulation. The initial supply is sent to the Treasury Account.
     * The maximum supply of tokens is 9,223,372,036,854,775,807(2^63-1)
     * tokens and is in the lowest denomination possible. For creating an
     * NFT, you must set the initial supply to 0.
     */
    private long initialSupply = 0;
    /**
     * The key which can perform token update and token delete operations on
     * the token.The admin key has the authority to change the freeze key,
     * wipe key, and KYC key. It can also update the treasury account of the
     * token.  If empty, the token can be perceived as immutable (not being
     * able to be updated/deleted). (KYC - Know Your Customer)
     */
    @Nullable
    private Key adminKey = null;
    /**
     * The key which can grant or revoke KYC of an account for the token's
     * transactions. If empty, KYC is not required, and KYC grant or revoke
     * operations are not possible.
     */
    @Nullable
    private Key kycKey = null;
    /**
     * The key which can sign to freeze or unfreeze an account for token
     * transactions. If empty, freezing is not possible.
     */
    @Nullable
    private Key freezeKey = null;
    /**
     * The key which can wipe the token balance of an account. If empty,
     * wipe is not possible.
     */
    @Nullable
    private Key wipeKey = null;
    /**
     * The key which can change the total supply of a token. This key is
     * used to authorize token mint and burn transactions. If this is left
     * empty, minting/burning tokens is not possible.
     */
    @Nullable
    private Key supplyKey = null;
    /**
     * The key that can change the token's  schedule. A custom fee schedule
     * token without a fee schedule key is immutable.
     */
    @Nullable
    private Key feeScheduleKey = null;
    /**
     * The key that has the authority to pause or unpause a token. Pausing
     * a token prevents the token from participating in all transactions.
     */
    @Nullable
    private Key pauseKey = null;
    /**
     * The key which can change the metadata of a token
     * (token definition, partition definition, and individual NFTs).
     */
    @Nullable
    private Key metadataKey = null;
    /**
     * The default Freeze status (frozen or unfrozen) of Hedera accounts
     * relative to this token. If true, an account must be unfrozen before
     * it can receive the token.
     */
    private boolean freezeDefault = false;
    /**
     * The epoch second at which the token should expire; if an auto-renew
     * account and period are specified, this is coerced to the current
     * epoch second plus the autoRenewPeriod. The default expiration time
     * is 90 days.
     */
    @Nullable
    private Instant expirationTime = null;
    /**
     * The interval at which the auto-renew account will be charged to
     * extend the token's expiry. The default auto-renew period is
     * 131,500 minutes. This is not currently enabled.
     */
    @Nullable
    private Duration autoRenewPeriod = null;
    /**
     * A short publicly visible memo about the token.
     */
    private String tokenMemo = "";
    /**
     * The type of token to create. Either fungible or non-fungible.
     */
    private TokenType tokenType = TokenType.FUNGIBLE_COMMON;
    /**
     * Specifies the token supply type. Defaults to INFINITE.
     */
    private TokenSupplyType tokenSupplyType = TokenSupplyType.INFINITE;
    /**
     * For tokens of type FUNGIBLE_COMMON - the maximum number of tokens that
     * can be in circulation.
     *
     * For tokens of type NON_FUNGIBLE_UNIQUE - the maximum number of NFTs
     * (serial numbers) that can be minted. This field can never be changed.
     *
     * You must set the token supply type to FINITE if you set this field.
     */
    private long maxSupply = 0;
    /**
     * Metadata of the created token definition.
     */
    private byte[] tokenMetadata = {};
    /**
     * Constructor.
     */
    public TokenCreateTransaction() {
        setAutoRenewPeriod(DEFAULT_AUTO_RENEW_PERIOD);
        defaultMaxTransactionFee = new Hbar(40);
    }

    /**
     * Constructor.
     *
     * @param txs Compound list of transaction id's list of (AccountId, Transaction)
     *            records
     * @throws InvalidProtocolBufferException       when there is an issue with the protobuf
     */
    TokenCreateTransaction(LinkedHashMap> txs) throws InvalidProtocolBufferException {
        super(txs);
        initFromTransactionBody();
    }

    /**
     * Constructor.
     *
     * @param txBody protobuf TransactionBody
     */
    TokenCreateTransaction(com.hedera.hashgraph.sdk.proto.TransactionBody txBody) {
        super(txBody);
        initFromTransactionBody();
    }

    /**
     * Extract the token name.
     *
     * @return                          the token name
     */
    @Nullable
    public String getTokenName() {
        return tokenName;
    }

    /**
     * Assign the token's name 100 bytes max.
     *
     * @param name                      the token name
     * @return {@code this}
     */
    public TokenCreateTransaction setTokenName(String name) {
        Objects.requireNonNull(name);
        requireNotFrozen();
        tokenName = name;
        return this;
    }

    /**
     * Extract the token symbol.
     *
     * @return                          the token symbol
     */
    public String getTokenSymbol() {
        return tokenSymbol;
    }

    /**
     * Assign the token's symbol 100 bytes max.
     *
     * @param symbol                    the token symbol
     * @return {@code this}
     */
    public TokenCreateTransaction setTokenSymbol(String symbol) {
        Objects.requireNonNull(symbol);
        requireNotFrozen();
        tokenSymbol = symbol;
        return this;
    }

    /**
     * Extract the decimals.
     *
     * @return                          the decimals
     */
    public int getDecimals() {
        return decimals;
    }

    /**
     * Assign the number of decimal places a token is divisible by.
     *
     * This field can never be changed.
     *
     * @param decimals                  the number of decimals
     * @return {@code this}
     */
    public TokenCreateTransaction setDecimals(@Nonnegative int decimals) {
        requireNotFrozen();
        this.decimals = decimals;
        return this;
    }

    /**
     * Extract the initial supply of tokens.
     *
     * @return                          the initial supply of tokens
     */
    public long getInitialSupply() {
        return initialSupply;
    }

    /**
     * Assign the initial supply of tokens.
     *
     * @param initialSupply             the initial supply of tokens
     * @return {@code this}
     */
    public TokenCreateTransaction setInitialSupply(@Nonnegative long initialSupply) {
        requireNotFrozen();
        this.initialSupply = initialSupply;
        return this;
    }

    /**
     * Extract the treasury account id.
     *
     * @return                          the treasury account id
     */
    @Nullable
    public AccountId getTreasuryAccountId() {
        return treasuryAccountId;
    }

    /**
     * Assign the treasury account id.
     *
     * @param accountId                 the treasury account id
     * @return {@code this}
     */
    public TokenCreateTransaction setTreasuryAccountId(AccountId accountId) {
        Objects.requireNonNull(accountId);
        requireNotFrozen();
        this.treasuryAccountId = accountId;
        return this;
    }

    /**
     * Extract the admin key.
     *
     * @return                          the admin key
     */
    @Nullable
    public Key getAdminKey() {
        return adminKey;
    }

    /**
     * Assign the admin key.
     *
     * @param key                       the admin key
     * @return {@code this}
     */
    public TokenCreateTransaction setAdminKey(Key key) {
        requireNotFrozen();
        Objects.requireNonNull(key);
        adminKey = key;
        return this;
    }

    /**
     * Extract the know your customer key.
     *
     * @return                          the know your customer key
     */
    @Nullable
    public Key getKycKey() {
        return kycKey;
    }

    /**
     * Assign the kyc key.
     *
     * @param key                       the know your customer key
     * @return {@code this}
     */
    public TokenCreateTransaction setKycKey(Key key) {
        requireNotFrozen();
        kycKey = key;
        return this;
    }

    /**
     * Extract the freeze key.
     *
     * @return                          the freeze key
     */
    @Nullable
    public Key getFreezeKey() {
        return freezeKey;
    }

    /**
     * Assign the freeze key.
     *
     * @param key                       the freeze key
     * @return {@code this}
     */
    public TokenCreateTransaction setFreezeKey(Key key) {
        Objects.requireNonNull(key);
        requireNotFrozen();
        freezeKey = key;
        return this;
    }

    /**
     * Extract the wipe key.
     *
     * @return                          the wipe key
     */
    @Nullable
    public Key getWipeKey() {
        return wipeKey;
    }

    /**
     * Assign the wipe key.
     *
     * @param key                       the wipe key
     * @return {@code this}
     */
    public TokenCreateTransaction setWipeKey(Key key) {
        Objects.requireNonNull(key);
        requireNotFrozen();
        wipeKey = key;
        return this;
    }

    /**
     * Extract the supply key.
     *
     * @return                          the supply key
     */
    @Nullable
    public Key getSupplyKey() {
        return supplyKey;
    }

    /**
     * Assign the supply key.
     *
     * @param key                       the supply key
     * @return {@code this}
     */
    public TokenCreateTransaction setSupplyKey(Key key) {
        Objects.requireNonNull(key);
        requireNotFrozen();
        supplyKey = key;
        return this;
    }

    /**
     * Extract the fee schedule key.
     *
     * @return                          the fee schedule key
     */
    @Nullable
    public Key getFeeScheduleKey() {
        return feeScheduleKey;
    }

    /**
     * Assign the fee schedule key.
     *
     * @param key                       the fee schedule key
     * @return {@code this}
     */
    public TokenCreateTransaction setFeeScheduleKey(Key key) {
        requireNotFrozen();
        Objects.requireNonNull(key);
        feeScheduleKey = key;
        return this;
    }

    /**
     * Extract the pause key.
     *
     * @return                          the pause key
     */
    @Nullable
    public Key getPauseKey() {
        return pauseKey;
    }

    /**
     * Assign the pause key.
     *
      * @param key                      the pause key
     * @return {@code this}
     */
    public TokenCreateTransaction setPauseKey(Key key) {
        requireNotFrozen();
        Objects.requireNonNull(key);
        pauseKey = key;
        return this;
    }

    /**
     * Extract the metadata key.
     *
     * @return                          the metadata key
     */
    @Nullable
    public Key getMetadataKey() {
        return metadataKey;
    }

    /**
     * Assign the metadata key.
     *
     * @param key                      the metadata key
     * @return {@code this}
     */
    public TokenCreateTransaction setMetadataKey(Key key) {
        requireNotFrozen();
        Objects.requireNonNull(key);
        metadataKey = key;
        return this;
    }

    /**
     * Extract the freeze default.
     *
     * @return                          the freeze default
     */
    public boolean getFreezeDefault() {
        return freezeDefault;
    }

    /**
     * Assign the freeze default.
     *
     * @param freezeDefault             the freeze default
     * @return {@code this}
     */
    public TokenCreateTransaction setFreezeDefault(boolean freezeDefault) {
        requireNotFrozen();
        this.freezeDefault = freezeDefault;
        return this;
    }

    /**
     * Extract the expiration time.
     *
     * @return                          the expiration time
     */
    @Nullable
    @SuppressFBWarnings(
        value = "EI_EXPOSE_REP",
        justification = "An Instant can't actually be mutated"
    )
    public Instant getExpirationTime() {
        return expirationTime;
    }

    /**
     * Assign the expiration time.
     *
     * @param expirationTime            the expiration time
     * @return {@code this}
     */
    @SuppressFBWarnings(
        value = "EI_EXPOSE_REP2",
        justification = "An Instant can't actually be mutated"
    )
    public TokenCreateTransaction setExpirationTime(Instant expirationTime) {
        Objects.requireNonNull(expirationTime);
        requireNotFrozen();
        autoRenewPeriod = null;
        this.expirationTime = expirationTime;
        return this;
    }

    /**
     * Extract the auto renew account id.
     *
     * @return                          the auto renew account id
     */
    @Nullable
    public AccountId getAutoRenewAccountId() {
        return autoRenewAccountId;
    }

    /**
     * Assign the auto renew account id.
     *
     * @param accountId                 the auto renew account id
     * @return {@code this}
     */
    public TokenCreateTransaction setAutoRenewAccountId(AccountId accountId) {
        Objects.requireNonNull(accountId);
        requireNotFrozen();
        this.autoRenewAccountId = accountId;
        return this;
    }

    /**
     * Extract the auto renew period.
     *
     * @return                          the auto renew period
     */
    @Nullable
    @SuppressFBWarnings(
        value = "EI_EXPOSE_REP",
        justification = "A Duration can't actually be mutated"
    )
    public Duration getAutoRenewPeriod() {
        return autoRenewPeriod;
    }

    /**
     * Assign the auto renew period.
     *
     * @param period                    the auto renew period
     * @return {@code this}
     */
    @SuppressFBWarnings(
        value = "EI_EXPOSE_REP2",
        justification = "A Duration can't actually be mutated"
    )
    public TokenCreateTransaction setAutoRenewPeriod(Duration period) {
        Objects.requireNonNull(period);
        requireNotFrozen();
        autoRenewPeriod = period;
        return this;
    }

    /**
     * Extract the token's memo 100 bytes max.
     *
     * @return                          the token's memo 100 bytes max
     */
    public String getTokenMemo() {
        return tokenMemo;
    }

    /**
     * Assign the token's memo.
     *
     * @param memo                      the token's memo 100 bytes max
     * @return {@code this}
     */
    public TokenCreateTransaction setTokenMemo(String memo) {
        Objects.requireNonNull(memo);
        requireNotFrozen();
        tokenMemo = memo;
        return this;
    }

    /**
     * Extract the custom fees.
     *
     * @return                          the custom fees
     */
    @Nullable
    public List getCustomFees() {
        return CustomFee.deepCloneList(customFees);
    }

    /**
     * Assign the custom fees.
     *
     * @param customFees                the custom fees
     * @return {@code this}
     */
    public TokenCreateTransaction setCustomFees(List customFees) {
        requireNotFrozen();
        this.customFees = CustomFee.deepCloneList(customFees);
        return this;
    }

    /**
     * Extract the token type.
     *
     * @return                          the token type
     */
    public TokenType getTokenType() {
        return tokenType;
    }

    /**
     * Assign the token type.
     *
     * @param tokenType                 the token type
     * @return {@code this}
     */
    public TokenCreateTransaction setTokenType(TokenType tokenType) {
        requireNotFrozen();
        Objects.requireNonNull(tokenType);
        this.tokenType = tokenType;
        return this;
    }

    /**
     * Extract the supply type.
     *
     * @return                          the supply type
     */
    public TokenSupplyType getSupplyType() {
        return tokenSupplyType;
    }

    /**
     * Assign the supply type.
     *
      * @param supplyType               the supply type
     * @return {@code this}
     */
    public TokenCreateTransaction setSupplyType(TokenSupplyType supplyType) {
        requireNotFrozen();
        Objects.requireNonNull(supplyType);
        tokenSupplyType = supplyType;
        return this;
    }

    /**
     * Extract the max supply of tokens.
     *
     * @return                          the max supply of tokens
     */
    public long getMaxSupply() {
        return maxSupply;
    }

    /**
     * Assign the max supply of tokens.
     *
     * @param maxSupply                 the max supply of tokens
     * @return {@code this}
     */
    public TokenCreateTransaction setMaxSupply(@Nonnegative long maxSupply) {
        requireNotFrozen();
        this.maxSupply = maxSupply;
        return this;
    }

    /**
     * Extract the token metadata.
     *
     * @return the token metadata
     */
    public byte[] getTokenMetadata() {
        return tokenMetadata;
    }

    /**
     * Assign the token metadata.
     *
     * @param tokenMetadata the token metadata
     * @return {@code this}
     */
    public TokenCreateTransaction setTokenMetadata(byte[] tokenMetadata) {
        requireNotFrozen();
        this.tokenMetadata = tokenMetadata;
        return this;
    }

    @Override
    public TokenCreateTransaction freezeWith(@Nullable Client client) {
        if (
            autoRenewPeriod != null &&
                autoRenewAccountId == null &&
                client != null &&
                client.getOperatorAccountId() != null
        ) {
            autoRenewAccountId = client.getOperatorAccountId();
        }

        return super.freezeWith(client);
    }

    /**
     * Build the transaction body.
     *
     * @return {@link com.hedera.hashgraph.sdk.proto.TokenCreateTransactionBody}
     */
    TokenCreateTransactionBody.Builder build() {
        var builder = TokenCreateTransactionBody.newBuilder();
        if (treasuryAccountId != null) {
            builder.setTreasury(treasuryAccountId.toProtobuf());
        }

        if (autoRenewAccountId != null) {
            builder.setAutoRenewAccount(autoRenewAccountId.toProtobuf());
        }
        builder.setName(tokenName);
        builder.setSymbol(tokenSymbol);
        builder.setDecimals(decimals);
        builder.setInitialSupply(initialSupply);
        if (adminKey != null) {
            builder.setAdminKey(adminKey.toProtobufKey());
        }
        if (kycKey != null) {
            builder.setKycKey(kycKey.toProtobufKey());
        }
        if (freezeKey != null) {
            builder.setFreezeKey(freezeKey.toProtobufKey());
        }
        if (wipeKey != null) {
            builder.setWipeKey(wipeKey.toProtobufKey());
        }
        if (supplyKey != null) {
            builder.setSupplyKey(supplyKey.toProtobufKey());
        }
        if (feeScheduleKey != null) {
            builder.setFeeScheduleKey(feeScheduleKey.toProtobufKey());
        }
        if (pauseKey != null) {
            builder.setPauseKey(pauseKey.toProtobufKey());
        }
        if (metadataKey != null) {
            builder.setMetadataKey(metadataKey.toProtobufKey());
        }
        builder.setFreezeDefault(freezeDefault);
        if (expirationTime != null) {
            builder.setExpiry(InstantConverter.toProtobuf(expirationTime));
        }
        if (autoRenewPeriod != null) {
            builder.setAutoRenewPeriod(DurationConverter.toProtobuf(autoRenewPeriod));
        }
        builder.setMemo(tokenMemo);
        builder.setTokenType(tokenType.code);
        builder.setSupplyType(tokenSupplyType.code);
        builder.setMaxSupply(maxSupply);
        builder.setMetadata(ByteString.copyFrom(tokenMetadata));

        for (var fee : customFees) {
            builder.addCustomFees(fee.toProtobuf());
        }

        return builder;
    }

    /**
     * Initialize from the transaction body.
     */
    void initFromTransactionBody() {
        var body = sourceTransactionBody.getTokenCreation();
        if (body.hasTreasury()) {
            treasuryAccountId = AccountId.fromProtobuf(body.getTreasury());
        }
        if (body.hasAutoRenewAccount()) {
            autoRenewAccountId = AccountId.fromProtobuf(body.getAutoRenewAccount());
        }
        tokenName = body.getName();
        tokenSymbol = body.getSymbol();
        decimals = body.getDecimals();
        initialSupply = body.getInitialSupply();
        if (body.hasAdminKey()) {
            adminKey = Key.fromProtobufKey(body.getAdminKey());
        }
        if (body.hasKycKey()) {
            kycKey = Key.fromProtobufKey(body.getKycKey());
        }
        if (body.hasFreezeKey()) {
            freezeKey = Key.fromProtobufKey(body.getFreezeKey());
        }
        if (body.hasWipeKey()) {
            wipeKey = Key.fromProtobufKey(body.getWipeKey());
        }
        if (body.hasSupplyKey()) {
            supplyKey = Key.fromProtobufKey(body.getSupplyKey());
        }
        if (body.hasFeeScheduleKey()) {
            feeScheduleKey = Key.fromProtobufKey(body.getFeeScheduleKey());
        }
        if (body.hasPauseKey()) {
            pauseKey = Key.fromProtobufKey(body.getPauseKey());
        }
        if (body.hasMetadataKey()) {
            metadataKey = Key.fromProtobufKey(body.getMetadataKey());
        }
        freezeDefault = body.getFreezeDefault();
        if (body.hasExpiry()) {
            expirationTime = InstantConverter.fromProtobuf(body.getExpiry());
        }
        if (body.hasAutoRenewPeriod()) {
            autoRenewPeriod = DurationConverter.fromProtobuf(body.getAutoRenewPeriod());
        }
        tokenMemo = body.getMemo();
        tokenType = TokenType.valueOf(body.getTokenType());
        tokenSupplyType = TokenSupplyType.valueOf(body.getSupplyType());
        maxSupply = body.getMaxSupply();
        tokenMetadata = body.getMetadata().toByteArray();

        for (var fee : body.getCustomFeesList()) {
            customFees.add(CustomFee.fromProtobuf(fee));
        }
    }

    @Override
    void validateChecksums(Client client) throws BadEntityIdException {
        for (var fee : customFees) {
            fee.validateChecksums(client);
        }

        if (treasuryAccountId != null) {
            treasuryAccountId.validateChecksum(client);
        }

        if (autoRenewAccountId != null) {
            autoRenewAccountId.validateChecksum(client);
        }
    }

    @Override
    MethodDescriptor getMethodDescriptor() {
        return TokenServiceGrpc.getCreateTokenMethod();
    }

    @Override
    void onFreeze(TransactionBody.Builder bodyBuilder) {
        bodyBuilder.setTokenCreation(build());
    }

    @Override
    void onScheduled(SchedulableTransactionBody.Builder scheduled) {
        scheduled.setTokenCreation(build());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy