Skip to content

Commit

Permalink
feat(HIP-904): Token Reject (#1888)
Browse files Browse the repository at this point in the history
Signed-off-by: Nikita Lebedev <[email protected]>
  • Loading branch information
thenswan authored Jul 22, 2024
1 parent b11f98c commit 1c63256
Show file tree
Hide file tree
Showing 10 changed files with 2,252 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
* [NFT Allowances](../examples/src/main/java/com/hedera/hashgraph/sdk/examples/NftAddRemoveAllowancesExample.java)
* [Zero token operations](../examples/src/main/java/com/hedera/hashgraph/sdk/examples/ZeroTokenOperationsExample.java)
* [Change Or Remove Existing Keys From A Token (HIP-540)](../examples/src/main/java/com/hedera/hashgraph/sdk/examples/ChangeRemoveTokenKeys.java)
* [Reject A Token (HIP-904)](../examples/src/main/java/com/hedera/hashgraph/sdk/examples/TokenRejectExample.java)

### File Service
* [Create a file](../examples/src/main/java/com/hedera/hashgraph/sdk/examples/CreateFileExample.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package com.hedera.hashgraph.sdk.examples;

import com.hedera.hashgraph.sdk.AccountBalanceQuery;
import com.hedera.hashgraph.sdk.AccountCreateTransaction;
import com.hedera.hashgraph.sdk.AccountDeleteTransaction;
import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Client;
import com.hedera.hashgraph.sdk.PrecheckStatusException;
import com.hedera.hashgraph.sdk.PrivateKey;
import com.hedera.hashgraph.sdk.ReceiptStatusException;
import com.hedera.hashgraph.sdk.TokenCreateTransaction;
import com.hedera.hashgraph.sdk.TokenDeleteTransaction;
import com.hedera.hashgraph.sdk.TokenMintTransaction;
import com.hedera.hashgraph.sdk.TokenRejectFlow;
import com.hedera.hashgraph.sdk.TokenRejectTransaction;
import com.hedera.hashgraph.sdk.TokenSupplyType;
import com.hedera.hashgraph.sdk.TokenType;
import com.hedera.hashgraph.sdk.TransferTransaction;
import io.github.cdimascio.dotenv.Dotenv;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeoutException;

public class TokenRejectExample {

// see `.env.sample` in the repository root for how to specify these values
// or set environment variables with the same names
private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID")));

private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY")));

// HEDERA_NETWORK defaults to testnet if not specified in dotenv
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");

private TokenRejectExample() {}

public static void main(String[] args)
throws TimeoutException, PrecheckStatusException, ReceiptStatusException, InterruptedException {
Client client = ClientHelper.forName(HEDERA_NETWORK);

// 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(OPERATOR_ID, OPERATOR_KEY);

// create a treasury account
var treasuryAccountPrivateKey = PrivateKey.generateED25519();
var treasuryAccountId = new AccountCreateTransaction()
.setKey(treasuryAccountPrivateKey.getPublicKey())
.setMaxAutomaticTokenAssociations(100)
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client)
.accountId;

// create a receiver account with unlimited max auto associations
var receiverAccountPrivateKey = PrivateKey.generateED25519();
var receiverAccountId = new AccountCreateTransaction()
.setKey(receiverAccountPrivateKey.getPublicKey())
.setMaxAutomaticTokenAssociations(-1)
.freezeWith(client)
.sign(receiverAccountPrivateKey)
.execute(client)
.getReceipt(client)
.accountId;

// create a fungible token
var fungibleTokenId = new TokenCreateTransaction()
.setTokenName("Example Fungible Token")
.setTokenSymbol("EFT")
.setTokenMemo("I was created for demo")
.setDecimals(0)
.setInitialSupply(1_000_000)
.setMaxSupply(1_000_000)
.setTreasuryAccountId(treasuryAccountId)
.setSupplyType(TokenSupplyType.FINITE)
.setAdminKey(treasuryAccountPrivateKey.getPublicKey())
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client)
.tokenId;

// create NFT
var nonFungibleTokenId = new TokenCreateTransaction()
.setTokenName("Example NFT")
.setTokenSymbol("ENFT")
.setTokenType(TokenType.NON_FUNGIBLE_UNIQUE)
.setTreasuryAccountId(treasuryAccountId)
.setSupplyType(TokenSupplyType.FINITE)
.setMaxSupply(3)
.setAdminKey(treasuryAccountPrivateKey.getPublicKey())
.setSupplyKey(treasuryAccountPrivateKey.getPublicKey())
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client)
.tokenId;

// mint 3 NFTs
var mintReceiptNftToken = new TokenMintTransaction()
.setTokenId(nonFungibleTokenId)
.setMetadata(generateNftMetadata((byte) 3))
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client);

var nftSerials = mintReceiptNftToken.serials;

// transfer the tokens to the receiver
new TransferTransaction()
.addTokenTransfer(fungibleTokenId, treasuryAccountId, -1_000)
.addTokenTransfer(fungibleTokenId, receiverAccountId, 1_000)
.addNftTransfer(nonFungibleTokenId.nft(nftSerials.get(0)), treasuryAccountId, receiverAccountId)
.addNftTransfer(nonFungibleTokenId.nft(nftSerials.get(1)), treasuryAccountId, receiverAccountId)
.addNftTransfer(nonFungibleTokenId.nft(nftSerials.get(2)), treasuryAccountId, receiverAccountId)
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client);

var receiverAccountBalance = new AccountBalanceQuery()
.setAccountId(receiverAccountId)
.execute(client);

System.out.println("Receiver account has: " + receiverAccountBalance.tokens.get(fungibleTokenId) + " example fungible tokens.");
System.out.println("Receiver account has: " + receiverAccountBalance.tokens.get(nonFungibleTokenId) + " example NFTs.");

System.out.println("Receiver rejects example fungible tokens...");

// reject the fungible token
new TokenRejectTransaction()
.setOwnerId(receiverAccountId)
.addTokenId(fungibleTokenId)
.freezeWith(client)
.sign(receiverAccountPrivateKey)
.execute(client)
.getReceipt(client);

System.out.println("Receiver rejects example NFTs...");

// execute the token reject flow
new TokenRejectFlow()
.setOwnerId(receiverAccountId)
.setNftIds(List.of(
nonFungibleTokenId.nft(nftSerials.get(0)),
nonFungibleTokenId.nft(nftSerials.get(1)),
nonFungibleTokenId.nft(nftSerials.get(2))
))
.freezeWith(client)
.sign(receiverAccountPrivateKey)
.execute(client)
.getReceipt(client);

var receiverAccountBalanceAfterTokenReject = new AccountBalanceQuery()
.setAccountId(receiverAccountId)
.execute(client);

System.out.println("Receiver account has (after executing TokenReject): " + receiverAccountBalanceAfterTokenReject.tokens.get(fungibleTokenId) + " example fungible tokens.");
System.out.println("Receiver account has (after executing TokenRejectFlow): " + receiverAccountBalanceAfterTokenReject.tokens.get(nonFungibleTokenId) + " example NFTs.");

var treasuryAccountBalance = new AccountBalanceQuery()
.setAccountId(treasuryAccountId)
.execute(client);

System.out.println("Treasury account has: " + treasuryAccountBalance.tokens.get(fungibleTokenId) + " example fungible tokens.");
System.out.println("Treasury account has: " + treasuryAccountBalance.tokens.get(nonFungibleTokenId) + " example NFTs.");

// clean up

new AccountDeleteTransaction()
.setAccountId(treasuryAccountId)
.setTransferAccountId(OPERATOR_ID)
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client);

new AccountDeleteTransaction()
.setAccountId(receiverAccountId)
.setTransferAccountId(OPERATOR_ID)
.freezeWith(client)
.sign(receiverAccountPrivateKey)
.execute(client);

new TokenDeleteTransaction()
.setTokenId(fungibleTokenId)
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client);

new TokenDeleteTransaction()
.setTokenId(nonFungibleTokenId)
.freezeWith(client)
.sign(treasuryAccountPrivateKey)
.execute(client)
.getReceipt(client);

client.close();
}

private static List<byte[]> generateNftMetadata(byte metadataCount) {
List<byte[]> metadatas = new ArrayList<>();

for (byte i = 0; i < metadataCount; i++) {
byte[] md = {i};
metadatas.add(md);
}

return metadatas;
}

}
Loading

0 comments on commit 1c63256

Please sign in to comment.