Skip to content

Commit

Permalink
feat(TCK): Implement TokenCreate (#2030)
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Ivanov <ivanivanov.ii726@gmail.com>
  • Loading branch information
0xivanov authored Oct 22, 2024
1 parent e372c1d commit dce06be
Show file tree
Hide file tree
Showing 9 changed files with 563 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.hedera.hashgraph.sdk.proto.Timestamp;
import com.hedera.hashgraph.sdk.proto.TimestampSeconds;
import java.time.Duration;
import java.time.Instant;

/**
Expand Down Expand Up @@ -66,6 +67,13 @@ static Timestamp toProtobuf(Instant instant) {
.build();
}

static Timestamp toProtobuf(Duration duration) {
return Timestamp.newBuilder()
.setSeconds(duration.getSeconds())
.setNanos(duration.getNano())
.build();
}

/**
* Convert an instance into a timestamp in seconds.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public class TokenCreateTransaction extends Transaction<TokenCreateTransaction>
*/
@Nullable
private Instant expirationTime = null;
private Duration expirationTimeDuration = null;
/**
* The interval at which the auto-renew account will be charged to
* extend the token's expiry. The default auto-renew period is
Expand Down Expand Up @@ -560,10 +561,20 @@ public TokenCreateTransaction setExpirationTime(Instant expirationTime) {
Objects.requireNonNull(expirationTime);
requireNotFrozen();
autoRenewPeriod = null;
this.expirationTimeDuration = null;
this.expirationTime = expirationTime;
return this;
}

public TokenCreateTransaction setExpirationTime(Duration expirationTime) {
Objects.requireNonNull(expirationTime);
requireNotFrozen();
autoRenewPeriod = null;
this.expirationTime = null;
this.expirationTimeDuration = expirationTime;
return this;
}

/**
* Extract the auto renew account id.
*
Expand Down Expand Up @@ -800,6 +811,10 @@ TokenCreateTransactionBody.Builder build() {
if (expirationTime != null) {
builder.setExpiry(InstantConverter.toProtobuf(expirationTime));
}
if (expirationTimeDuration != null) {
builder.setExpiry(InstantConverter.toProtobuf(expirationTimeDuration));
}

if (autoRenewPeriod != null) {
builder.setAutoRenewPeriod(DurationConverter.toProtobuf(autoRenewPeriod));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import java.time.Instant;

/**
* AccountCreateService for account related methods
* AccountService for account related methods
*/
@JSONRPC2Service
public class AccountService extends AbstractJSONRPC2Service {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

/**
* SdkService for managing the {@link Client} setup and reset
Expand All @@ -42,6 +43,7 @@ public class SdkService extends AbstractJSONRPC2Service {

@JSONRPC2Method("setup")
public SetupResponse setup(final SetupParams params) throws Exception {
var clientExecutor = Executors.newFixedThreadPool(16);
String clientType;
if (params.getNodeIp().isPresent()
&& params.getNodeAccountId().isPresent()
Expand All @@ -50,12 +52,12 @@ public SetupResponse setup(final SetupParams params) throws Exception {
Map<String, AccountId> node = new HashMap<>();
var nodeId = AccountId.fromString(params.getNodeAccountId().get());
node.put(params.getNodeIp().get(), nodeId);
client = Client.forNetwork(node);
client = Client.forNetwork(node, clientExecutor);
clientType = "custom";
client.setMirrorNetwork(List.of(params.getMirrorNetworkIp().get()));
} else {
// Default to testnet
client = Client.forTestnet();
client = Client.forTestnet(clientExecutor);
clientType = "testnet";
}

Expand All @@ -66,7 +68,8 @@ public SetupResponse setup(final SetupParams params) throws Exception {
}

@JSONRPC2Method("reset")
public SetupResponse reset() {
public SetupResponse reset() throws Exception {
client.closeChannels();
client = null;
return new SetupResponse("");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/*-
*
* Hedera Java SDK
*
* Copyright (C) 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.tck.methods.sdk;

import com.google.protobuf.InvalidProtocolBufferException;
import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.CustomFixedFee;
import com.hedera.hashgraph.sdk.CustomFractionalFee;
import com.hedera.hashgraph.sdk.CustomRoyaltyFee;
import com.hedera.hashgraph.sdk.Status;
import com.hedera.hashgraph.sdk.TokenCreateTransaction;
import com.hedera.hashgraph.sdk.TokenId;
import com.hedera.hashgraph.sdk.TokenSupplyType;
import com.hedera.hashgraph.sdk.TokenType;
import com.hedera.hashgraph.sdk.TransactionReceipt;
import com.hedera.hashgraph.tck.annotation.JSONRPC2Method;
import com.hedera.hashgraph.tck.annotation.JSONRPC2Service;
import com.hedera.hashgraph.tck.methods.AbstractJSONRPC2Service;
import com.hedera.hashgraph.tck.methods.sdk.param.TokenCreateParams;
import com.hedera.hashgraph.tck.methods.sdk.response.TokenResponse;
import com.hedera.hashgraph.tck.util.KeyUtils;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

/**
* TokenService for token related methods
*/
@JSONRPC2Service
public class TokenService extends AbstractJSONRPC2Service {

private final SdkService sdkService;

public TokenService(SdkService sdkService) {
this.sdkService = sdkService;
}

@JSONRPC2Method("createToken")
public TokenResponse createToken(final TokenCreateParams params) throws Exception {
TokenCreateTransaction tokenCreateTransaction = new TokenCreateTransaction();

params.getAdminKey().ifPresent(key -> {
try {
tokenCreateTransaction.setAdminKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getKycKey().ifPresent(key -> {
try {
tokenCreateTransaction.setKycKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getFreezeKey().ifPresent(key -> {
try {
tokenCreateTransaction.setFreezeKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getWipeKey().ifPresent(key -> {
try {
tokenCreateTransaction.setWipeKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getSupplyKey().ifPresent(key -> {
try {
tokenCreateTransaction.setSupplyKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getFeeScheduleKey().ifPresent(key -> {
try {
tokenCreateTransaction.setFeeScheduleKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getPauseKey().ifPresent(key -> {
try {
tokenCreateTransaction.setPauseKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getMetadataKey().ifPresent(key -> {
try {
tokenCreateTransaction.setMetadataKey(KeyUtils.getKeyFromString(key));
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e);
}
});

params.getName().ifPresent(tokenCreateTransaction::setTokenName);
params.getSymbol().ifPresent(tokenCreateTransaction::setTokenSymbol);
params.getDecimals().ifPresent(decimals -> tokenCreateTransaction.setDecimals(decimals.intValue()));
params.getInitialSupply()
.ifPresent(initialSupply -> tokenCreateTransaction.setInitialSupply(Long.parseLong(initialSupply)));

params.getTreasuryAccountId()
.ifPresent(treasuryAccountId ->
tokenCreateTransaction.setTreasuryAccountId(AccountId.fromString(treasuryAccountId)));

params.getFreezeDefault().ifPresent(tokenCreateTransaction::setFreezeDefault);

params.getExpirationTime()
.ifPresent(expirationTime ->
tokenCreateTransaction.setExpirationTime(Duration.ofSeconds(Long.parseLong(expirationTime))));

params.getAutoRenewAccountId()
.ifPresent(autoRenewAccountId ->
tokenCreateTransaction.setAutoRenewAccountId(AccountId.fromString(autoRenewAccountId)));

params.getAutoRenewPeriod()
.ifPresent(autoRenewPeriodSeconds -> tokenCreateTransaction.setAutoRenewPeriod(
Duration.ofSeconds(Long.parseLong(autoRenewPeriodSeconds))));

params.getMemo().ifPresent(tokenCreateTransaction::setTokenMemo);
params.getTokenType().ifPresent(tokenType -> {
if (tokenType.equals("ft")) {
tokenCreateTransaction.setTokenType(TokenType.FUNGIBLE_COMMON);
} else if (tokenType.equals("nft")) {
tokenCreateTransaction.setTokenType(TokenType.NON_FUNGIBLE_UNIQUE);
} else {
throw new IllegalArgumentException("Invalid token type");
}
});

params.getSupplyType().ifPresent(supplyType -> {
if (supplyType.equals("infinite")) {
tokenCreateTransaction.setSupplyType(TokenSupplyType.INFINITE);
} else if (supplyType.equals("finite")) {
tokenCreateTransaction.setSupplyType(TokenSupplyType.FINITE);
} else {
throw new IllegalArgumentException("Invalid supply type");
}
});

params.getMaxSupply().ifPresent(maxSupply -> tokenCreateTransaction.setMaxSupply(Long.valueOf(maxSupply)));

params.getCustomFees().ifPresent(customFees -> {
List<com.hedera.hashgraph.sdk.CustomFee> customFeeList = new ArrayList<>();
for (var customFee : customFees) {
// set fixed fees
customFee.getFixedFee().ifPresent(fixedFee -> {
var sdkFixedFee = new CustomFixedFee()
.setAmount(Long.parseLong(fixedFee.getAmount()))
.setFeeCollectorAccountId(AccountId.fromString(customFee.getFeeCollectorAccountId()))
.setAllCollectorsAreExempt(customFee.getFeeCollectorsExempt());
fixedFee.getDenominatingTokenId()
.ifPresent(tokenID -> sdkFixedFee.setDenominatingTokenId(TokenId.fromString(tokenID)));
customFeeList.add(sdkFixedFee);
});

// set fractional fees
customFee.getFractionalFee().ifPresent(fractionalFee -> {
var sdkFractionalFee = new CustomFractionalFee()
.setNumerator(Long.parseLong(fractionalFee.getNumerator()))
.setDenominator(Long.parseLong(fractionalFee.getDenominator()))
.setMin(Long.parseLong(fractionalFee.getMinimumAmount()))
.setMax(Long.parseLong(fractionalFee.getMaximumAmount()))
.setFeeCollectorAccountId(AccountId.fromString(customFee.getFeeCollectorAccountId()))
.setAllCollectorsAreExempt(customFee.getFeeCollectorsExempt());

customFeeList.add(sdkFractionalFee);
});

// set royalty fees
customFee.getRoyaltyFee().ifPresent(royaltyFee -> {
var sdkRoyaltyFee = new CustomRoyaltyFee()
.setDenominator(Long.parseLong(royaltyFee.getDenominator()))
.setNumerator(Long.parseLong(royaltyFee.getNumerator()))
.setFeeCollectorAccountId(AccountId.fromString(customFee.getFeeCollectorAccountId()))
.setAllCollectorsAreExempt(customFee.getFeeCollectorsExempt());

royaltyFee.getFallbackFee().ifPresent(fallbackFee -> {
var fixedFallback = new CustomFixedFee().setAmount(Long.parseLong(fallbackFee.getAmount()));
fallbackFee
.getDenominatingTokenId()
.ifPresent(
tokenID -> fixedFallback.setDenominatingTokenId(TokenId.fromString(tokenID)));
sdkRoyaltyFee.setFallbackFee(fixedFallback);
});
customFeeList.add(sdkRoyaltyFee);
});
}
tokenCreateTransaction.setCustomFees(customFeeList);
});

params.getMetadata().ifPresent(metadata -> tokenCreateTransaction.setTokenMetadata(metadata.getBytes()));

params.getCommonTransactionParams()
.ifPresent(commonTransactionParams ->
commonTransactionParams.fillOutTransaction(tokenCreateTransaction, sdkService.getClient()));

TransactionReceipt transactionReceipt =
tokenCreateTransaction.execute(sdkService.getClient()).getReceipt(sdkService.getClient());

String tokenId = "";
if (transactionReceipt.status == Status.SUCCESS) {
tokenId = transactionReceipt.tokenId.toString();
}

return new TokenResponse(tokenId, transactionReceipt.status);
}
}
Loading

0 comments on commit dce06be

Please sign in to comment.