Tutorials
No Results
Tutorial

Beginner · 15 minutes or less

Creating a Java Transaction with the PureStake API

Creating a transaction and sending it in to the network programmatically are foundational tasks for working with a blockchain. Using the PureStake API allows a developer full access to the complete Algorand MainNet/Testnet ledgers without running any infrastructure, but does require a few minor changes to the code.

Requirements

Background

Steps

1. Set Up Dependencies

Signing and submitting a transaction in Java requires a fair number of imports. Here is a skeleton sample of a Java package with the required dependencies imported:

import com.algorand.algosdk.account.Account;
import com.algorand.algosdk.v2.client.common.AlgodClient;
import com.algorand.algosdk.v2.client.model.PendingTransactionResponse;
import com.algorand.algosdk.v2.client.model.TransactionParametersResponse;
import com.algorand.algosdk.v2.client.model.PostTransactionsResponse;
import com.algorand.algosdk.transaction.SignedTransaction;
import com.algorand.algosdk.transaction.Transaction;
import com.algorand.algosdk.util.Encoder;
import org.apache.commons.lang3.ArrayUtils;

public class SubmitTx {
    public static void main(String[] args) throws Exception {

    }
}

2. Setting Up the client to Connect to the PureStake API

First, you’ll need to set the default configuration values for PureStake’s API. This process requires to add an additional header to the AlgodClient.

To do that, enter the following:

final String ALGOD_API_ADDR = "https://testnet-algorand.api.purestake.io/ps2";
final int  ALGOD_PORT = 443;
final String ALGOD_API_TOKEN = "";

String[] headers = {"X-API-Key"};
String[] values = {"YOUR API KEY HER"};

AlgodClient client = new AlgodClient(ALGOD_API_ADDR, ALGOD_PORT, ALGOD_API_TOKEN);

3. Recover Account

Now you’ll need to recover your account using your mnemonic.

Important Note: Mnemonics control your account. Never share them or store insecurely. The code below is for demonstration purposes only.

final String SRC_ACCOUNT = "YOUR MNEMONIC HERE";
Account src = new Account(SRC_ACCOUNT);

4. Get and Set Transaction Parameters

Get the transaction parameters from the blockchain using the client object and set the amount and destination address.

TransactionParametersResponse params = client.TransactionParams().execute(headers, values).body();
Long amount = 1L;

5. Create and Sign Transaction

Create a new transaction using the parameters defined above and sign it.

Transaction tx = Transaction.PaymentTransactionBuilder().sender(src.getAddress()).receiver(DEST_ADDR).amount(amount).suggestedParams(params).build();
SignedTransaction signedTx = src.signTransaction(tx);

6. Include Verification Method

After the transaction is complete and sent in, this method is called to verify that the transaction has been included in the blockchain:

// Function from Algorand Inc. - Utility function to wait on a transaction to be confirmed
public static void waitForConfirmation(AlgodClient client, String txID, String[] headers, String[] values) throws Exception {
    Long lastRound = client.GetStatus().execute(headers, values).body().lastRound;
    while (true) {
        try {
            // Check the pending tranactions
            PendingTransactionResponse pendingInfo = client.PendingTransactionInformation(txID).execute(headers, values).body();
            if (pendingInfo.confirmedRound != null && pendingInfo.confirmedRound > 0) {
                System.out.println("Transaction confirmed in round " + pendingInfo.confirmedRound);
                break;
            }
            lastRound++;
            client.WaitForBlock(lastRound).execute(headers, values);
        } catch (Exception e) {
            throw (e);
        }
    }
}

7. Submit and Verify Transaction

Lastly, send the signed transaction to the blockchain. You’ll need to add an additional header to this call with the PureStake expected Content-Type

try {
    String[] txHeaders = ArrayUtils.add(headers, "Content-Type");
    String[] txValues = ArrayUtils.add(values, "application/x-binary");
    byte[] encodedTxBytes = Encoder.encodeToMsgPack(signedTx);
    PostTransactionsResponse txResponse = client.RawTransaction().rawtxn(encodedTxBytes).execute(txHeaders, txValues).body();
    System.out.println("Successfully sent tx with ID " + txResponse.txId);
    waitForConfirmation(client, txResponse.txId, headers, values);
} catch (Exception e) {
    System.err.println("Exception when calling algod#rawTransaction: " + e);
}

You should see a response similar to this one:

Transaction sent with ID FLU7QOHB5ZNNMIBXGS35KLNQS6ZTGR4HJOZKUZBBCI2DPZCZJGIQ
Transaction confirmed in round 10461724

8. Run All of the Code Together

If you’d rather just drop in the code in its entirety, copy below. You’ll need to enter your API key, your mnemonic, and some other specifics in order for it to function properly.

import com.algorand.algosdk.account.Account;
import com.algorand.algosdk.v2.client.common.AlgodClient;
import com.algorand.algosdk.v2.client.model.PendingTransactionResponse;
import com.algorand.algosdk.v2.client.model.TransactionParametersResponse;
import com.algorand.algosdk.v2.client.model.PostTransactionsResponse;
import com.algorand.algosdk.transaction.SignedTransaction;
import com.algorand.algosdk.transaction.Transaction;
import com.algorand.algosdk.util.Encoder;
import org.apache.commons.lang3.ArrayUtils;

public class SubmitTx {
    // Function from Algorand Inc. - Utility function to wait on a transaction to be confirmed
    public static void waitForConfirmation(AlgodClient client, String txID, String[] headers, String[] values) throws Exception {
        Long lastRound = client.GetStatus().execute(headers, values).body().lastRound;
        while (true) {
            try {
                // Check the pending tranactions
                PendingTransactionResponse pendingInfo = client.PendingTransactionInformation(txID).execute(headers, values).body();
                if (pendingInfo.confirmedRound != null && pendingInfo.confirmedRound > 0) {
                    System.out.println("Transaction confirmed in round " + pendingInfo.confirmedRound);
                    break;
                }
                lastRound++;
                client.WaitForBlock(lastRound).execute(headers, values);
            } catch (Exception e) {
                throw (e);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        final String ALGOD_API_ADDR = "https://testnet-algorand.api.purestake.io/ps2";
        final int  ALGOD_PORT = 443;
        final String ALGOD_API_TOKEN = "";

        String[] headers = {"X-API-Key"};
        String[] values = {"YOUR API KEY HERE"};

        AlgodClient client = new AlgodClient(ALGOD_API_ADDR, ALGOD_PORT, ALGOD_API_TOKEN);

        final String SRC_ACCOUNT = "YOUR MNEMONIC HERE"; 
        Account src = new Account(SRC_ACCOUNT);

        final String DEST_ADDR = "ZHGZZQ2PIWYRK6MIK44GKO3VGQUC7NS2V3UQ63M3DIMFUFGI4BRWK7WDBU";

        TransactionParametersResponse params = client.TransactionParams().execute(headers, values).body();
        Long amount = 10L;

        Transaction tx = Transaction.PaymentTransactionBuilder().sender(src.getAddress()).receiver(DEST_ADDR).amount(amount).suggestedParams(params).build();
        SignedTransaction signedTx = src.signTransaction(tx);

        // send the transaction to the network
        try {
            String[] txHeaders = ArrayUtils.add(headers, "Content-Type");
            String[] txValues = ArrayUtils.add(values, "application/x-binary");
            byte[] encodedTxBytes = Encoder.encodeToMsgPack(signedTx);
            PostTransactionsResponse txResponse = client.RawTransaction().rawtxn(encodedTxBytes).execute(txHeaders, txValues).body();
            System.out.println("Transaction sent with ID " + txResponse.txId);
            waitForConfirmation(client, txResponse.txId, headers, values);
        } catch (Exception e) {
            System.err.println("Exception when calling algod#rawTransaction: " + e);
        }
    }
}

transactions

PureStake

java

v2 api

November 13, 2020