Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add transaction status checks to examples #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 49 additions & 44 deletions hcs/src/main/java/hcs/ScriptHcsTopic.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class ScriptHcsTopic {
public static void main(String[] args) throws Exception {
System.out.println("🏁 Hello Future World - HCS Topic - start");

// Load environment variables from .env file
Dotenv dotenv = Dotenv.configure().directory("../").load();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the .env file is located in the parent directory. please revert this change here and in the other locations too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it did not run with that location for the .env which is why I had to move it. can you run this again please?

// Load environment variables from .env file
Dotenv dotenv = Dotenv.configure().directory("./").load();
String operatorIdStr = dotenv.get("OPERATOR_ACCOUNT_ID");
String operatorKeyStr = dotenv.get("OPERATOR_ACCOUNT_PRIVATE_KEY");
if (operatorIdStr == null || operatorKeyStr == null) {
Expand All @@ -33,75 +33,82 @@ public static void main(String[] args) throws Exception {
operatorKeyStr = operatorKeyStr.substring(2);
}

// Initialize the operator account
// Initialize the operator account
AccountId operatorId = AccountId.fromString(operatorIdStr);
PrivateKey operatorKey = PrivateKey.fromStringECDSA(operatorKeyStr);
Client client = Client.forTestnet().setOperator(operatorId, operatorKey);
System.out.println("Using account: " + operatorIdStr);

//Set the default maximum transaction fee (in HBAR)
// Set the default maximum transaction fee (in HBAR)
client.setDefaultMaxTransactionFee(new Hbar(100));
//Set the default maximum payment for queries (in HBAR)
// Set the default maximum payment for queries (in HBAR)
client.setDefaultMaxQueryPayment(new Hbar(50));

// Create a Hedera Consensus Service (HCS) topic
System.out.println("🟣 Creating new HCS topic");
TopicCreateTransaction topicCreateTx = new TopicCreateTransaction()
.setTopicMemo("Hello Future World topic - xyz")
// Freeze the transaction to prepare for signing
.freezeWith(client);
.setTopicMemo("Hello Future World topic - xyz")
// Freeze the transaction to prepare for signing
.freezeWith(client);

// Get the transaction ID of the transaction.
// The SDK automatically generates and assigns a transaction ID when the transaction is created
// The SDK automatically generates and assigns a transaction ID when the
// transaction is created
TransactionId topicCreateTxId = topicCreateTx.getTransactionId();
System.out.println("The topic create transaction ID: " + topicCreateTxId.toString());

// Sign the transaction with the account key that will be paying for this transaction
// Sign the transaction with the account key that will be paying for this
// transaction
TopicCreateTransaction topicCreateTxSigned = topicCreateTx.sign(operatorKey);

// Submit the transaction to the Hedera Testnet
TransactionResponse topicCreateTxSubmitted = topicCreateTxSigned.execute(client);

// Get the transaction receipt
// Check transaction status for topic creation
TransactionReceipt topicCreateTxReceipt = topicCreateTxSubmitted.getReceipt(client);
if (topicCreateTxReceipt.status != Status.SUCCESS) {
throw new RuntimeException(
"❌ Topic creation transaction failed with status: " + topicCreateTxReceipt.status);
}

// Get the topic ID
TopicId topicId = topicCreateTxReceipt.topicId;
System.out.println("Topic ID:" + topicId.toString());
System.out.println("Topic created successfully. Topic ID: " + topicId.toString());

// Publish a message to the Hedera Consensus Service (HCS) topic
System.out.println("🟣 Publish message to HCS topic");
TopicMessageSubmitTransaction topicMsgSubmitTx = new TopicMessageSubmitTransaction()
//Set the transaction memo with the hello future world ID
.setTransactionMemo("Hello Future World topic message - xyz")
.setTopicId(topicId)
//Set the topic message contents
.setMessage("Hello HCS!")
// Freeze the transaction to prepare for signing
.freezeWith(client);
// Set the transaction memo with the hello future world ID
.setTransactionMemo("Hello Future World topic message - xyz")
.setTopicId(topicId)
// Set the topic message contents
.setMessage("Hello HCS!")
// Freeze the transaction to prepare for signing
.freezeWith(client);

// Get the transaction ID of the transaction.
// The SDK automatically generates and assigns a transaction ID when the transaction is created
// The SDK automatically generates and assigns a transaction ID when the
// transaction is created
TransactionId topicMsgSubmitTxId = topicMsgSubmitTx.getTransactionId();
System.out.println(
"The topic message submit transaction ID: " +
topicMsgSubmitTxId.toString()
);
"The topic message submit transaction ID: " +
topicMsgSubmitTxId.toString());

// Sign the transaction with the account key that will be paying for this transaction
// Sign the transaction with the account key that will be paying for this
// transaction
TopicMessageSubmitTransaction topicMsgSubmitTxSigned = topicMsgSubmitTx.sign(operatorKey);

// Submit the transaction to the Hedera Testnet
TransactionResponse topicMsgSubmitTxSubmitted =
topicMsgSubmitTxSigned.execute(client);
TransactionResponse topicMsgSubmitTxSubmitted = topicMsgSubmitTxSigned.execute(client);

// Get the transaction receipt
TransactionReceipt topicMsgSubmitTxReceipt =
topicMsgSubmitTxSubmitted.getReceipt(client);
// Check transaction status for message submission
TransactionReceipt topicMsgSubmitTxReceipt = topicMsgSubmitTxSubmitted.getReceipt(client);
if (topicMsgSubmitTxReceipt.status != Status.SUCCESS) {
throw new RuntimeException(
"❌ Topic message submission transaction failed with status: " + topicMsgSubmitTxReceipt.status);
}

// Get the topic message sequence number
Long topicMsgSeqNum = topicMsgSubmitTxReceipt.topicSequenceNumber;
System.out.println("Topic Message Sequence Number:" + topicMsgSeqNum.toString());
System.out.println(" Message submitted successfully. Sequence Number: " + topicMsgSeqNum.toString());

client.close();

Expand All @@ -112,32 +119,30 @@ public static void main(String[] args) throws Exception {
System.out.println("🟣 View the topic on HashScan");
String topicHashscanUrl = "https://hashscan.io/testnet/topic/" + topicId.toString();
System.out.println(
"Topic Hashscan URL:\n" +
topicHashscanUrl
);
"Topic Hashscan URL:\n" +
topicHashscanUrl);

// Wait for 6s for record files (blocks) to propagate to mirror nodes
Thread.sleep(6000);

// Verify topic using Mirror Node API
System.out.println("Get topic data from the Hedera Mirror Node");
String topicMirrorNodeApiUrl =
"https://testnet.mirrornode.hedera.com/api/v1/topics/" + topicId.toString() + "/messages?encoding=base64&limit=5&order=asc&sequencenumber=1";
String topicMirrorNodeApiUrl = "https://testnet.mirrornode.hedera.com/api/v1/topics/" + topicId.toString()
+ "/messages?encoding=base64&limit=5&order=asc&sequencenumber=1";
System.out.println(
"The topic Hedera Mirror Node API URL:\n" +
topicMirrorNodeApiUrl
);
"The topic Hedera Mirror Node API URL:\n" +
topicMirrorNodeApiUrl);
final HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(topicMirrorNodeApiUrl))
.build();
.uri(URI.create(topicMirrorNodeApiUrl))
.build();
final HttpClient httpClient = HttpClient.newHttpClient();
final var mirrorNodeResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body();
JsonObject jsonResponse = JsonParser.parseString(mirrorNodeResponse).getAsJsonObject();

// Extract messages from the JSON (null check equivalent)
JsonArray topicVerifyMessages = jsonResponse.has("messages")
? jsonResponse.getAsJsonArray("messages")
: new JsonArray();
? jsonResponse.getAsJsonArray("messages")
: new JsonArray();
System.out.println("Number of messages retrieved from this topic: " + topicVerifyMessages.size());
List<String> topicVerifyMessagesParsed = new ArrayList<>();
for (JsonElement messageElement : topicVerifyMessages) {
Expand Down
77 changes: 39 additions & 38 deletions transfer/src/main/java/transfer/ScriptTransferHbar.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class ScriptTransferHbar {
public static void main(String[] args) throws Exception {
System.out.println("🏁 Hello Future World - Transfer HBAR - start");

// Load environment variables from .env file
Dotenv dotenv = Dotenv.configure().directory("../").load();
// Load environment variables from .env file
Dotenv dotenv = Dotenv.configure().directory("./").load();
String operatorIdStr = dotenv.get("OPERATOR_ACCOUNT_ID");
String operatorKeyStr = dotenv.get("OPERATOR_ACCOUNT_PRIVATE_KEY");
if (operatorIdStr == null || operatorKeyStr == null) {
Expand All @@ -33,37 +33,39 @@ public static void main(String[] args) throws Exception {
operatorKeyStr = operatorKeyStr.substring(2);
}

// Initialize the operator account
// Initialize the operator account
AccountId operatorId = AccountId.fromString(operatorIdStr);
PrivateKey operatorKey = PrivateKey.fromStringECDSA(operatorKeyStr);
Client client = Client.forTestnet().setOperator(operatorId, operatorKey);
System.out.println("Using account: " + operatorIdStr);

//Set the default maximum transaction fee (in HBAR)
// Set the default maximum transaction fee (in HBAR)
client.setDefaultMaxTransactionFee(new Hbar(100));
//Set the default maximum payment for queries (in HBAR)
// Set the default maximum payment for queries (in HBAR)
client.setDefaultMaxQueryPayment(new Hbar(50));

System.out.println("🟣 Creating, signing, and submitting the transfer transaction");
AccountId recipientAccount1 = AccountId.fromString("0.0.200");
AccountId recipientAccount2 = AccountId.fromString("0.0.201");
TransferTransaction transferTx = new TransferTransaction()
.setTransactionMemo("Hello Future World transfer - xyz")
// Debit 3 HBAR from the operator account (sender)
.addHbarTransfer(operatorId, Hbar.from(-3, HbarUnit.HBAR))
// Credit 1 HBAR to account 0.0.200 (1st recipient)
.addHbarTransfer(recipientAccount1, Hbar.from(1, HbarUnit.HBAR))
// Credit 2 HBAR to account 0.0.201 (2nd recipient)
.addHbarTransfer(recipientAccount2, Hbar.from(2, HbarUnit.HBAR))
// Freeze the transaction to prepare for signing
.freezeWith(client);
.setTransactionMemo("Hello Future World transfer - xyz")
// Debit 3 HBAR from the operator account (sender)
.addHbarTransfer(operatorId, Hbar.from(-3, HbarUnit.HBAR))
// Credit 1 HBAR to account 0.0.200 (1st recipient)
.addHbarTransfer(recipientAccount1, Hbar.from(1, HbarUnit.HBAR))
// Credit 2 HBAR to account 0.0.201 (2nd recipient)
.addHbarTransfer(recipientAccount2, Hbar.from(2, HbarUnit.HBAR))
// Freeze the transaction to prepare for signing
.freezeWith(client);

// Get the transaction ID for the transfer transaction
TransactionId transferTxId = transferTx.getTransactionId();
System.out.println("The transfer transaction ID: " + transferTxId.toString());

// Sign the transaction with the account that is being debited (operator account) and the transaction fee payer account (operator account)
// Since the account that is being debited and the account that is paying for the transaction are the same, only one account's signature is required
// Sign the transaction with the account that is being debited (operator
// account) and the transaction fee payer account (operator account)
// Since the account that is being debited and the account that is paying for
// the transaction are the same, only one account's signature is required
TransferTransaction transferTxSigned = transferTx.sign(operatorKey);

// Submit the transaction to the Hedera Testnet
Expand All @@ -72,42 +74,42 @@ public static void main(String[] args) throws Exception {
// Get the transfer transaction receipt
TransactionReceipt transferTxReceipt = transferTxSubmitted.getReceipt(client);
Status transactionStatus = transferTxReceipt.status;
System.out.println(
"The transfer transaction status is: " +
transactionStatus.toString()
);

// Check if the transaction was successful
if (transactionStatus == Status.SUCCESS) {
System.out.println("✅ The transfer transaction was successful.");
System.out.println("Transaction Hashscan URL:\nhttps://hashscan.io/testnet/transaction/" + transferTxId);
} else {
System.err.println("❌ The transfer transaction failed with status: " + transactionStatus);
throw new RuntimeException("Transaction failed: " + transactionStatus);
}

// Query HBAR balance using AccountBalanceQuery
AccountBalance newAccountBalance = new AccountBalanceQuery()
.setAccountId(operatorId)
.execute(client);
.setAccountId(operatorId)
.execute(client);
Hbar newHbarBalance = newAccountBalance.hbars;
System.out.println(
"The new account balance after the transfer: " +
newHbarBalance.toString()
);
"The new account balance after the transfer: " +
newHbarBalance.toString());

client.close();

// View the transaction in HashScan
System.out.println(
"🟣 View the transfer transaction transaction in HashScan"
);
String transferTxVerifyHashscanUrl =
"https://hashscan.io/testnet/transaction/" + transferTxId;
"🟣 View the transfer transaction transaction in HashScan");
String transferTxVerifyHashscanUrl = "https://hashscan.io/testnet/transaction/" + transferTxId;
System.out.println(
"Transaction Hashscan URL:\n" +
transferTxVerifyHashscanUrl
);
"Transaction Hashscan URL:\n" +
transferTxVerifyHashscanUrl);

// Verify transfer transaction using Mirror Node API
System.out.println("🟣 Get transfer transaction data from the Hedera Mirror Node");
Thread.sleep(6_000);

String transferTxIdMirrorNodeFormat =
convertTransactionIdForMirrorNodeApi(transferTxId.toString());
String transferTxVerifyMirrorNodeApiUrl =
"https://testnet.mirrornode.hedera.com/api/v1/transactions/" + transferTxIdMirrorNodeFormat + "?nonce=0";
String transferTxIdMirrorNodeFormat = convertTransactionIdForMirrorNodeApi(transferTxId.toString());
String transferTxVerifyMirrorNodeApiUrl = "https://testnet.mirrornode.hedera.com/api/v1/transactions/"
+ transferTxIdMirrorNodeFormat + "?nonce=0";

final HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(transferTxVerifyMirrorNodeApiUrl))
Expand All @@ -131,8 +133,7 @@ public static void main(String[] args) throws Exception {
}
}
filteredAndSortedTransfers.sort(
Comparator.comparingLong(obj -> obj.get("amount").getAsLong())
);
Comparator.comparingLong(obj -> obj.get("amount").getAsLong()));

System.out.printf("%-15s %-15s%n", "AccountID", "Amount");
System.out.println("-".repeat(30));
Expand Down