diff --git a/astro.sidebar.ts b/astro.sidebar.ts index 3247e09a..833cac06 100644 --- a/astro.sidebar.ts +++ b/astro.sidebar.ts @@ -208,6 +208,16 @@ export const sidebar = [ }), ], }), + group("build.group.sdks.java-sdk", { + collapsed: true, + items: [ + "build/sdks/java-sdk", + "build/sdks/java-sdk/quickstart", + "build/sdks/java-sdk/account", + "build/sdks/java-sdk/building-transactions", + "build/sdks/java-sdk/java-examples", + ], + }), // Python SDK (no subpages found) "build/sdks/python-sdk", // Unity SDK (no subpages found) diff --git a/src/content/docs/build/sdks.mdx b/src/content/docs/build/sdks.mdx index 7c5e548e..1b249bcb 100644 --- a/src/content/docs/build/sdks.mdx +++ b/src/content/docs/build/sdks.mdx @@ -20,6 +20,8 @@ Use these Aptos software development kits (SDKs), in combination with the [Aptos + + diff --git a/src/content/docs/build/sdks/java-sdk.mdx b/src/content/docs/build/sdks/java-sdk.mdx new file mode 100644 index 00000000..445a9d1e --- /dev/null +++ b/src/content/docs/build/sdks/java-sdk.mdx @@ -0,0 +1,179 @@ +--- +title: "Java SDK" +description: "Official Java SDK for building applications on Aptos - comprehensive cryptography, multi-signature support, and hierarchical deterministic wallets" +sidebar: + label: "Java SDK Overview" +--- + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +
+ + ![Github Repo Stars](https://img.shields.io/github/stars/aptos-labs/japtos) + + + + ![Static Badge](https://img.shields.io/badge/SDK_Reference-Docs) + +
+ +The Java SDK (Japtos) allows you to connect, explore, and interact with the Aptos blockchain from Java applications. It provides comprehensive support for account management, transaction signing, multi-signature accounts, and hierarchical deterministic wallets. + +## Installation + +### Maven + +Add the GitHub Packages repository and dependency to your `pom.xml`: + +```xml filename="pom.xml" + + + github + https://maven.pkg.github.com/aptos-labs/japtos + + + + + + com.aptos-labs + japtos + 1.1.0 + + +``` + +:::note +GitHub Packages requires authentication. See the [GitHub Packages Maven Registry documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry) for setup instructions. +::: + +### Manual Installation + +If you prefer to build from source, you can clone the repository and install it locally: + +```shellscript filename="Terminal" +git clone https://github.com/aptos-labs/japtos.git +cd japtos +mvn clean install +``` + +## Key Features + +- **Advanced Cryptography**: Ed25519 and MultiEd25519 signature schemes +- **Hierarchical Deterministic Wallets**: BIP39/BIP44 support with mnemonic phrases +- **Multi-Signature Accounts**: Threshold-based multi-signature transactions +- **BCS Serialization**: Binary Canonical Serialization for Aptos transactions +- **HTTP Client**: Robust REST client for Aptos API interactions +- **Comprehensive Testing**: Extensive test suite covering all functionality + +## Examples + + + + + + + + + + + +## Network Support + +The SDK supports all Aptos networks: + +```java +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.client.AptosClient; + +// Connect to different networks +AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.MAINNET) // or TESTNET, DEVNET, LOCALNET + .build(); + +AptosClient client = new AptosClient(config); +``` + +:::caution +Account funding via the faucet is only available on **Devnet** and **Localnet**. For Mainnet and Testnet, you'll need to fund accounts through other means (exchanges, faucets, etc.). +::: + +## Transfer APT Example + +Here's a quick example of how to transfer APT tokens: + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.transaction.*; +import com.aptoslabs.japtos.types.*; + +// Setup client +AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); +AptosClient client = new AptosClient(config); + +// Create accounts +Ed25519Account alice = Ed25519Account.generate(); +Ed25519Account bob = Ed25519Account.generate(); + +// Fund accounts (devnet only) +client.fundAccount(alice.getAccountAddress(), 100_000_000); +client.fundAccount(bob.getAccountAddress(), 100_000_000); + +// Build transfer transaction +ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("coin") +); + +TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(new TypeTag.Struct(new StructTag( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_coin"), + new Identifier("AptosCoin"), + Arrays.asList() + ))), + Arrays.asList( + new TransactionArgument.AccountAddress(bob.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) // 0.01 APT + ) +); + +// Get account sequence number and chain ID +long sequenceNumber = client.getAccountSequenceNumber(alice.getAccountAddress()); +int chainId = client.getChainId(); + +// Build and sign transaction +RawTransaction rawTx = new RawTransaction( + alice.getAccountAddress(), + sequenceNumber, + payload, + 1000000L, // maxGasAmount + 100L, // gasUnitPrice + System.currentTimeMillis() / 1000 + 3600, // expiration + chainId +); + +SignedTransaction signedTx = new SignedTransaction( + rawTx, + alice.signTransactionWithAuthenticator(rawTx) +); + +// Submit and wait for transaction +PendingTransaction pendingTx = client.submitTransaction(signedTx); +Transaction tx = client.waitForTransaction(pendingTx.getHash()); + +System.out.println("Transaction completed: " + tx.isSuccess()); +``` + +## Resources + +- [GitHub Repository](https://github.com/aptos-labs/japtos) +- [Quickstart Guide](/build/sdks/java-sdk/quickstart) +- [Account Management](/build/sdks/java-sdk/account) +- [Building Transactions](/build/sdks/java-sdk/building-transactions) + diff --git a/src/content/docs/build/sdks/java-sdk/account.mdx b/src/content/docs/build/sdks/java-sdk/account.mdx new file mode 100644 index 00000000..d1731ffc --- /dev/null +++ b/src/content/docs/build/sdks/java-sdk/account.mdx @@ -0,0 +1,297 @@ +--- +title: "Creating and Managing Accounts" +description: "Learn how to generate, fund, and manage Aptos accounts using the Java SDK with Ed25519, multi-signature, and hierarchical deterministic wallets" +sidebar: + label: "Managing Accounts" +--- + +import { Aside } from '@astrojs/starlight/components'; + +The Java SDK provides comprehensive support for various account types and key management schemes. You can create single-key accounts, multi-signature accounts, and derive accounts from hierarchical deterministic (HD) wallets. + +## Single-Key Accounts (Ed25519) + +The most common way to create an account is using the Ed25519 signature scheme. + +### Generate a New Account + +```java +import com.aptoslabs.japtos.account.Ed25519Account; + +// Generate a new Ed25519 account +Ed25519Account account = Ed25519Account.generate(); + +// Access account properties +System.out.println("Address: " + account.getAccountAddress()); +System.out.println("Public Key: " + account.getPublicKey()); +System.out.println("Private Key: " + account.getPrivateKey()); +``` + +### Create Account from Private Key + +If you already have a private key, you can create an account from it: + +```java +import com.aptoslabs.japtos.core.crypto.Ed25519PrivateKey; + +// Create account from existing private key +Ed25519PrivateKey privateKey = Ed25519PrivateKey.fromHex("your_private_key_hex"); +Ed25519Account account = new Ed25519Account(privateKey, null); +``` + +### Funding Accounts + +Once you have generated credentials, you must fund the account for the network to recognize it. + +On **devnet** or **localnet**, you can use the faucet: + +```java +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.api.AptosConfig; + +AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); +AptosClient client = new AptosClient(config); + +// Fund account with 1 APT (100_000_000 octas) +client.fundAccount(account.getAccountAddress(), 100_000_000); +``` + + + +## Hierarchical Deterministic (HD) Wallets + +The Java SDK supports BIP39 mnemonic phrases and BIP44 derivation paths for creating deterministic wallets. + +### Derive Account from Mnemonic + +```java +import com.aptoslabs.japtos.account.Account; + +// Standard BIP39 mnemonic phrase +String mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + +// BIP44 derivation path for Aptos (coin type: 637) +String derivationPath = "m/44'/637'/0'/0'/0'"; + +// Derive account +Ed25519Account account = Account.fromDerivationPath(derivationPath, mnemonic); +System.out.println("Derived address: " + account.getAccountAddress()); +``` + +### Derive Multiple Accounts + +You can derive multiple accounts from the same mnemonic by changing the account index: + +```java +String mnemonic = "your mnemonic phrase here"; + +// First account +Ed25519Account account0 = Account.fromDerivationPath( + "m/44'/637'/0'/0'/0'", + mnemonic +); + +// Second account +Ed25519Account account1 = Account.fromDerivationPath( + "m/44'/637'/1'/0'/0'", + mnemonic +); + +// Third account +Ed25519Account account2 = Account.fromDerivationPath( + "m/44'/637'/2'/0'/0'", + mnemonic +); +``` + +### Convert Entropy to Mnemonic + +You can generate a mnemonic phrase from entropy (such as a UUID): + +```java +import com.aptoslabs.japtos.utils.Bip39Utils; + +// Convert UUID/entropy to mnemonic phrase +String entropy = "9b4c9e83-a06e-4704-bc5f-b6a55d0dbb89"; +String mnemonic = Bip39Utils.entropyToMnemonic(entropy); + +System.out.println("Mnemonic: " + mnemonic); +// Output: "defense balance boat index fatal book remain champion cushion city escape huge" +``` + +## Multi-Signature Accounts + +Multi-signature accounts allow multiple parties to control an account. Transactions require a minimum threshold of signatures to be valid. + +### Create a 1-of-2 Multi-Signature Account + +```java +import com.aptoslabs.japtos.account.MultiEd25519Account; +import com.aptoslabs.japtos.core.crypto.Ed25519PrivateKey; +import java.util.Arrays; +import java.util.List; + +// Create two individual accounts +Ed25519Account account1 = Ed25519Account.generate(); +Ed25519Account account2 = Ed25519Account.generate(); + +// Create multi-signature account with 1-of-2 threshold +List privateKeys = Arrays.asList( + account1.getPrivateKey(), + account2.getPrivateKey() +); + +MultiEd25519Account multiAccount = MultiEd25519Account.fromPrivateKeys( + privateKeys, + 1 // threshold: only 1 signature required +); + +System.out.println("Multi-sig address: " + multiAccount.getAccountAddress()); +``` + +### Create a 2-of-3 Multi-Signature Account + +For higher security, you can require multiple signatures: + +```java +// Create three individual accounts +Ed25519Account account1 = Ed25519Account.generate(); +Ed25519Account account2 = Ed25519Account.generate(); +Ed25519Account account3 = Ed25519Account.generate(); + +// Create multi-signature account with 2-of-3 threshold +List privateKeys = Arrays.asList( + account1.getPrivateKey(), + account2.getPrivateKey(), + account3.getPrivateKey() +); + +MultiEd25519Account multiAccount = MultiEd25519Account.fromPrivateKeys( + privateKeys, + 2 // threshold: 2 signatures required +); +``` + +### Multi-Signature with Specific Signers + +You can create a multi-signature account where only specific keys can sign: + +```java +import com.aptoslabs.japtos.core.crypto.Ed25519PublicKey; + +// Create accounts +Ed25519Account account1 = Ed25519Account.generate(); +Ed25519Account account2 = Ed25519Account.generate(); +Ed25519Account account3 = Ed25519Account.generate(); + +// Only account1 and account2 can sign +List signers = Arrays.asList(account1, account2); + +// But all three public keys are part of the multi-sig +List publicKeys = Arrays.asList( + account1.getPublicKey(), + account2.getPublicKey(), + account3.getPublicKey() +); + +// Create multi-sig account (2-of-3, but only first 2 can actually sign) +MultiEd25519Account multiAccount = MultiEd25519Account.from( + signers, + publicKeys, + 2 // threshold +); +``` + +## Signing Messages + +All account types support message signing and verification: + +```java +// Sign a message +String message = "Hello, Aptos!"; +byte[] messageBytes = message.getBytes(); +Signature signature = account.sign(messageBytes); + +// Verify signature +boolean isValid = account.verifySignature(messageBytes, signature); +System.out.println("Signature valid: " + isValid); +``` + +## Account Address Formats + +Aptos account addresses are 32-byte values typically represented as hexadecimal strings: + +```java +import com.aptoslabs.japtos.types.AccountAddress; + +// Create from hex string (with or without 0x prefix) +AccountAddress address1 = AccountAddress.fromHex("0x1"); +AccountAddress address2 = AccountAddress.fromHex("0000000000000000000000000000000000000000000000000000000000000001"); + +// Both represent the same address (0x1) +System.out.println(address1.toString()); // 0x1 +System.out.println(address2.toString()); // 0x1 +``` + +## Best Practices + +1. **Never expose private keys**: Store private keys securely and never commit them to version control +2. **Use HD wallets for multiple accounts**: Derive multiple accounts from a single mnemonic for easier backup +3. **Secure mnemonic phrases**: Treat mnemonic phrases like passwords - they can recover all derived accounts +4. **Test on devnet first**: Always test your account management code on devnet before using it on mainnet +5. **Multi-sig for high-value accounts**: Use multi-signature accounts for enhanced security on important accounts + +## Example: Complete Account Workflow + +Here's a complete example showing account creation, funding, and balance checking: + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.types.AccountAddress; +import com.google.gson.JsonObject; + +public class AccountWorkflow { + public static void main(String[] args) throws Exception { + // Setup client + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // Generate account + Ed25519Account account = Ed25519Account.generate(); + System.out.println("Generated address: " + account.getAccountAddress()); + + // Fund account + client.fundAccount(account.getAccountAddress(), 100_000_000); + System.out.println("Account funded!"); + + // Check balance + String resourceType = "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>"; + JsonObject resource = client.getAccountResource( + account.getAccountAddress(), + resourceType + ); + long balance = resource.getAsJsonObject("coin") + .get("value") + .getAsLong(); + + System.out.println("Balance: " + balance + " octas"); + System.out.println("Balance: " + (balance / 100_000_000.0) + " APT"); + } +} +``` + +## Related Documentation + +- [Building Transactions](/build/sdks/java-sdk/building-transactions) +- [Java SDK Examples](/build/sdks/java-sdk/java-examples) +- [BIP39 Specification](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) +- [BIP44 Specification](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) + diff --git a/src/content/docs/build/sdks/java-sdk/building-transactions.mdx b/src/content/docs/build/sdks/java-sdk/building-transactions.mdx new file mode 100644 index 00000000..4122131d --- /dev/null +++ b/src/content/docs/build/sdks/java-sdk/building-transactions.mdx @@ -0,0 +1,516 @@ +--- +title: "Building Transactions" +description: "Learn how to build, sign, simulate, and submit transactions using the Aptos Java SDK" +sidebar: + label: "Building Transactions" +--- + +import { Aside } from '@astrojs/starlight/components'; + +Transactions are the primary way to interact with the Aptos blockchain. They allow you to transfer tokens, call smart contract functions, deploy modules, and more. + +## Transaction Lifecycle + +A typical transaction flow involves: + +1. **Build** - Create a `RawTransaction` with the transaction details +2. **Sign** - Sign the transaction with the sender's private key +3. **Submit** - Send the signed transaction to the network +4. **Wait** - Wait for the transaction to be executed +5. **Verify** - Check the transaction result + +## Basic Transaction Structure + +Every transaction in Aptos requires: + +- **Sender** - The account address sending the transaction +- **Sequence Number** - The current sequence number of the sender's account +- **Payload** - The action to perform (transfer, function call, etc.) +- **Max Gas Amount** - Maximum gas willing to pay +- **Gas Unit Price** - Price per unit of gas +- **Expiration Timestamp** - When the transaction expires +- **Chain ID** - The network chain identifier + +## Transferring APT + +The most common transaction type is transferring APT tokens between accounts. + +### Simple Transfer + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.transaction.*; +import com.aptoslabs.japtos.types.*; +import java.util.Arrays; + +// Setup +AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); +AptosClient client = new AptosClient(config); + +// Create accounts +Ed25519Account sender = Ed25519Account.generate(); +Ed25519Account receiver = Ed25519Account.generate(); + +// Fund sender +client.fundAccount(sender.getAccountAddress(), 100_000_000); + +// Build transfer payload +ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") +); + +TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), // type arguments (empty for simple transfer) + Arrays.asList( + new TransactionArgument.AccountAddress(receiver.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) // 0.01 APT + ) +); + +// Get account info +long sequenceNumber = client.getAccountSequenceNumber(sender.getAccountAddress()); +int chainId = client.getChainId(); + +// Build raw transaction +RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + sequenceNumber, + payload, + 200000L, // maxGasAmount + 100L, // gasUnitPrice + System.currentTimeMillis() / 1000 + 600, // expires in 10 minutes + chainId +); + +// Sign and submit +SignedTransaction signedTx = new SignedTransaction( + rawTx, + sender.signTransactionWithAuthenticator(rawTx) +); + +PendingTransaction pendingTx = client.submitTransaction(signedTx); +System.out.println("Transaction hash: " + pendingTx.getHash()); + +// Wait for completion +Transaction completedTx = client.waitForTransaction(pendingTx.getHash()); +System.out.println("Success: " + completedTx.isSuccess()); +``` + +### Transfer with Coin Type + +To transfer other coin types (not just APT), specify the coin type as a type argument: + +```java +// Transfer USDC (example) +TypeTag coinType = new TypeTag.Struct(new StructTag( + AccountAddress.fromHex("0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa"), + new Identifier("asset"), + new Identifier("USDC"), + Arrays.asList() +)); + +ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("coin") +); + +TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(coinType), // type argument for coin type + Arrays.asList( + new TransactionArgument.AccountAddress(receiver.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) + ) +); +``` + +## Calling Smart Contract Functions + +You can call any public entry function on deployed Move modules. + +### Entry Function Call + +```java +// Call a custom module function +// Format: :::: + +ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x123..."), // module owner address + new Identifier("my_module") +); + +TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("my_function"), + Arrays.asList(), // type arguments + Arrays.asList( + new TransactionArgument.U64(100L), + new TransactionArgument.Bool(true), + new TransactionArgument.String("hello") + ) +); + +// Build and submit transaction as shown above +``` + +### Common Transaction Arguments + +The SDK supports various argument types: + +```java +// Numbers +new TransactionArgument.U8((byte) 42) +new TransactionArgument.U16((short) 1000) +new TransactionArgument.U32(100000) +new TransactionArgument.U64(1000000L) +new TransactionArgument.U128(new BigInteger("1000000000")) +new TransactionArgument.U256(new BigInteger("1000000000000")) + +// Boolean +new TransactionArgument.Bool(true) + +// String +new TransactionArgument.String("hello world") + +// Address +new TransactionArgument.AccountAddress( + AccountAddress.fromHex("0x1") +) + +// Vectors +new TransactionArgument.U8Vector(new byte[]{1, 2, 3}) +new TransactionArgument.Vector(Arrays.asList( + new TransactionArgument.U64(100L), + new TransactionArgument.U64(200L) +)) +``` + +## Multi-Signature Transactions + +Multi-signature accounts can sign transactions that require multiple approvals. + +```java +import com.aptoslabs.japtos.account.MultiEd25519Account; + +// Create multi-sig account (2-of-3) +Ed25519Account account1 = Ed25519Account.generate(); +Ed25519Account account2 = Ed25519Account.generate(); +Ed25519Account account3 = Ed25519Account.generate(); + +List privateKeys = Arrays.asList( + account1.getPrivateKey(), + account2.getPrivateKey(), + account3.getPrivateKey() +); + +MultiEd25519Account multiSigAccount = MultiEd25519Account.fromPrivateKeys( + privateKeys, + 2 // threshold: 2 signatures required +); + +// Fund multi-sig account +client.fundAccount(multiSigAccount.getAccountAddress(), 100_000_000); + +// Build transaction (same as single-key) +RawTransaction rawTx = new RawTransaction( + multiSigAccount.getAccountAddress(), + sequenceNumber, + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + chainId +); + +// Sign with multi-sig account (automatically uses threshold signatures) +SignedTransaction signedTx = new SignedTransaction( + rawTx, + multiSigAccount.signTransactionWithAuthenticator(rawTx) +); + +// Submit normally +PendingTransaction pendingTx = client.submitTransaction(signedTx); +``` + +## Transaction Simulation + +Before submitting a transaction, you can simulate it to estimate gas costs and check for errors. + +```java +// Build raw transaction +RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + sequenceNumber, + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + chainId +); + +// Simulate transaction (doesn't require signing) +SimulationResult simulation = client.simulateTransaction(rawTx, sender); + +System.out.println("Gas used: " + simulation.getGasUsed()); +System.out.println("Success: " + simulation.isSuccess()); + +if (!simulation.isSuccess()) { + System.out.println("Error: " + simulation.getVmStatus()); +} +``` + + + +## Binary Canonical Serialization (BCS) + +The Java SDK automatically handles BCS serialization for transactions. However, you can also use BCS directly for custom serialization needs. + +```java +import com.aptoslabs.japtos.bcs.Serializer; +import com.aptoslabs.japtos.bcs.Deserializer; + +// Serialize data +Serializer serializer = new Serializer(); +serializer.serializeU64(123456L); +serializer.serializeString("hello"); +byte[] bytes = serializer.toBytes(); + +// Deserialize data +Deserializer deserializer = new Deserializer(bytes); +long value = deserializer.deserializeU64(); +String text = deserializer.deserializeString(); +``` + +## Gas Management + +### Estimating Gas + +Gas costs depend on: +- Transaction complexity +- Storage usage +- Network congestion + +```java +// Typical gas values for common transactions +long simpleTransferGas = 200000L; // ~0.002 APT at 100 gas price +long functionCallGas = 500000L; // ~0.005 APT at 100 gas price +long modulePublishGas = 2000000L; // ~0.02 APT at 100 gas price + +// Gas unit price (in octas) +long gasUnitPrice = 100L; // Standard price + +// Calculate max fee +long maxFee = maxGasAmount * gasUnitPrice; +System.out.println("Max fee: " + maxFee + " octas"); +``` + +### Setting Gas Parameters + +```java +RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + sequenceNumber, + payload, + 500000L, // maxGasAmount - increase for complex transactions + 150L, // gasUnitPrice - increase for faster processing + System.currentTimeMillis() / 1000 + 600, + chainId +); +``` + + + +## Transaction Status + +After submission, you can check transaction status: + +```java +// Submit transaction +PendingTransaction pendingTx = client.submitTransaction(signedTx); + +// Wait with timeout (blocks until completion) +Transaction completedTx = client.waitForTransaction( + pendingTx.getHash(), + 30 // timeout in seconds (optional) +); + +// Check status +if (completedTx.isSuccess()) { + System.out.println("Transaction succeeded!"); + System.out.println("Gas used: " + completedTx.getGasUsed()); +} else { + System.out.println("Transaction failed!"); + System.out.println("Error: " + completedTx.getVmStatus()); +} +``` + +## Error Handling + +Always implement proper error handling for transactions: + +```java +try { + // Build transaction + RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + sequenceNumber, + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + chainId + ); + + // Sign and submit + SignedTransaction signedTx = new SignedTransaction( + rawTx, + sender.signTransactionWithAuthenticator(rawTx) + ); + + PendingTransaction pendingTx = client.submitTransaction(signedTx); + + // Wait for completion + Transaction completedTx = client.waitForTransaction(pendingTx.getHash()); + + if (!completedTx.isSuccess()) { + throw new RuntimeException("Transaction failed: " + completedTx.getVmStatus()); + } + + System.out.println("Transaction successful!"); + +} catch (SequenceNumberException e) { + System.err.println("Incorrect sequence number: " + e.getMessage()); +} catch (InsufficientBalanceException e) { + System.err.println("Insufficient balance: " + e.getMessage()); +} catch (TransactionException e) { + System.err.println("Transaction error: " + e.getMessage()); +} catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); +} +``` + +## Complete Transaction Example + +Here's a complete, production-ready transaction example: + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.transaction.*; +import com.aptoslabs.japtos.types.*; +import java.util.Arrays; + +public class TransactionExample { + public static void main(String[] args) { + try { + // Setup + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // Load or create accounts + Ed25519Account sender = Ed25519Account.generate(); + Ed25519Account receiver = Ed25519Account.generate(); + + // Fund accounts + client.fundAccount(sender.getAccountAddress(), 100_000_000); + + // Build transfer payload + ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") + ); + + TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), + Arrays.asList( + new TransactionArgument.AccountAddress(receiver.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) + ) + ); + + // Get account sequence number and chain ID + long sequenceNumber = client.getAccountSequenceNumber( + sender.getAccountAddress() + ); + int chainId = client.getChainId(); + + // Build raw transaction + RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + sequenceNumber, + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + chainId + ); + + // Simulate before submitting + SimulationResult simulation = client.simulateTransaction(rawTx, sender); + System.out.println("Estimated gas: " + simulation.getGasUsed()); + + if (!simulation.isSuccess()) { + throw new RuntimeException("Simulation failed: " + simulation.getVmStatus()); + } + + // Sign transaction + SignedTransaction signedTx = new SignedTransaction( + rawTx, + sender.signTransactionWithAuthenticator(rawTx) + ); + + // Submit transaction + PendingTransaction pendingTx = client.submitTransaction(signedTx); + System.out.println("Transaction submitted: " + pendingTx.getHash()); + + // Wait for completion + Transaction completedTx = client.waitForTransaction(pendingTx.getHash()); + + if (completedTx.isSuccess()) { + System.out.println("Transaction succeeded!"); + System.out.println("Gas used: " + completedTx.getGasUsed()); + } else { + System.err.println("Transaction failed: " + completedTx.getVmStatus()); + } + + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + e.printStackTrace(); + } + } +} +``` + +## Best Practices + +1. **Always simulate transactions** before submitting to check for errors +2. **Set appropriate gas limits** - not too low (fails) or too high (wastes limits) +3. **Handle sequence numbers carefully** - use `client.getAccountSequenceNumber()` for each transaction +4. **Implement retry logic** for network failures +5. **Check transaction status** after submission +6. **Set reasonable expiration times** (typically 5-10 minutes) +7. **Use appropriate network** (devnet for testing, mainnet for production) + +## Related Documentation + +- [Managing Accounts](/build/sdks/java-sdk/account) +- [Java SDK Examples](/build/sdks/java-sdk/java-examples) +- [Aptos Transaction Guide](/build/guides/first-transaction) + diff --git a/src/content/docs/build/sdks/java-sdk/java-examples.mdx b/src/content/docs/build/sdks/java-sdk/java-examples.mdx new file mode 100644 index 00000000..fdd32a13 --- /dev/null +++ b/src/content/docs/build/sdks/java-sdk/java-examples.mdx @@ -0,0 +1,435 @@ +--- +title: "Java SDK Example Code" +description: "Comprehensive collection of example code and reference implementations for the Aptos Java SDK" +sidebar: + label: "Examples" +--- + +import { Steps } from '@astrojs/starlight/components'; + +For sample code explaining core concepts of the Java SDK, see: + +- [Quickstart](/build/sdks/java-sdk/quickstart) +- [Managing Accounts](/build/sdks/java-sdk/account) +- [Building Transactions](/build/sdks/java-sdk/building-transactions) + +Below are additional resources for specific use cases. + +## SDK Repository Examples + +The SDK repository contains comprehensive test suites demonstrating all functionality: + +### Test Suites + +The SDK includes extensive tests covering: + +- **Basic Account Tests** - Account generation, key management, and address derivation +- **Multi-Signature Tests** - 1-of-2, 1-of-3, and complex multi-signature setups +- **HD Wallet Tests** - BIP39 mnemonic generation, BIP44 path derivation, and UUID to mnemonic conversion +- **Transaction Tests** - APT transfers with single and multi-signature accounts +- **Integration Tests** - End-to-end workflows from account creation to transaction execution + +### Running the Tests + + + 1. Clone the repository + + ```shellscript filename="Terminal" + git clone https://github.com/aptos-labs/japtos.git + cd japtos + ``` + + 2. Run all tests + + ```shellscript filename="Terminal" + mvn test + ``` + + 3. Run specific test class + + ```shellscript filename="Terminal" + mvn test -Dtest=MultiKeyTests + ``` + + 4. Run specific test method + + ```shellscript filename="Terminal" + mvn test -Dtest=MultiKeyTests#testMultikeyPathDerivation + ``` + + +## Common Use Cases + +### Example 1: Simple APT Transfer + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.api.AptosConfig; +import com.aptoslabs.japtos.client.AptosClient; +import com.aptoslabs.japtos.transaction.*; +import com.aptoslabs.japtos.types.*; +import java.util.Arrays; + +public class SimpleTransfer { + public static void main(String[] args) throws Exception { + // Connect to devnet + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // Create and fund accounts + Ed25519Account alice = Ed25519Account.generate(); + Ed25519Account bob = Ed25519Account.generate(); + + client.fundAccount(alice.getAccountAddress(), 100_000_000); + + // Build and submit transfer + ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") + ); + + TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), + Arrays.asList( + new TransactionArgument.AccountAddress(bob.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) + ) + ); + + RawTransaction rawTx = new RawTransaction( + alice.getAccountAddress(), + client.getAccountSequenceNumber(alice.getAccountAddress()), + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + client.getChainId() + ); + + SignedTransaction signedTx = new SignedTransaction( + rawTx, + alice.signTransactionWithAuthenticator(rawTx) + ); + + PendingTransaction pending = client.submitTransaction(signedTx); + Transaction result = client.waitForTransaction(pending.getHash()); + + System.out.println("Transfer complete: " + result.isSuccess()); + } +} +``` + +### Example 2: Multi-Signature Account Transfer + +```java +import com.aptoslabs.japtos.account.MultiEd25519Account; +import com.aptoslabs.japtos.core.crypto.Ed25519PrivateKey; +import java.util.Arrays; + +public class MultiSigTransfer { + public static void main(String[] args) throws Exception { + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // Create 2-of-3 multi-sig account + Ed25519Account acc1 = Ed25519Account.generate(); + Ed25519Account acc2 = Ed25519Account.generate(); + Ed25519Account acc3 = Ed25519Account.generate(); + + MultiEd25519Account multiSig = MultiEd25519Account.fromPrivateKeys( + Arrays.asList( + acc1.getPrivateKey(), + acc2.getPrivateKey(), + acc3.getPrivateKey() + ), + 2 // threshold: 2 signatures required + ); + + // Fund multi-sig account + client.fundAccount(multiSig.getAccountAddress(), 100_000_000); + + // Create recipient + Ed25519Account recipient = Ed25519Account.generate(); + + // Build transfer (same as single-key) + ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") + ); + + TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), + Arrays.asList( + new TransactionArgument.AccountAddress(recipient.getAccountAddress()), + new TransactionArgument.U64(5_000_000L) + ) + ); + + RawTransaction rawTx = new RawTransaction( + multiSig.getAccountAddress(), + client.getAccountSequenceNumber(multiSig.getAccountAddress()), + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + client.getChainId() + ); + + // Sign with multi-sig (uses 2 of 3 keys automatically) + SignedTransaction signedTx = new SignedTransaction( + rawTx, + multiSig.signTransactionWithAuthenticator(rawTx) + ); + + PendingTransaction pending = client.submitTransaction(signedTx); + Transaction result = client.waitForTransaction(pending.getHash()); + + System.out.println("Multi-sig transfer complete: " + result.isSuccess()); + } +} +``` + +### Example 3: HD Wallet Account Derivation + +```java +import com.aptoslabs.japtos.account.Account; +import com.aptoslabs.japtos.utils.Bip39Utils; + +public class HDWalletExample { + public static void main(String[] args) throws Exception { + // Generate mnemonic from entropy + String entropy = "9b4c9e83-a06e-4704-bc5f-b6a55d0dbb89"; + String mnemonic = Bip39Utils.entropyToMnemonic(entropy); + + System.out.println("Mnemonic: " + mnemonic); + + // Derive multiple accounts from same mnemonic + Ed25519Account account0 = Account.fromDerivationPath( + "m/44'/637'/0'/0'/0'", + mnemonic + ); + + Ed25519Account account1 = Account.fromDerivationPath( + "m/44'/637'/1'/0'/0'", + mnemonic + ); + + Ed25519Account account2 = Account.fromDerivationPath( + "m/44'/637'/2'/0'/0'", + mnemonic + ); + + System.out.println("Account 0: " + account0.getAccountAddress()); + System.out.println("Account 1: " + account1.getAccountAddress()); + System.out.println("Account 2: " + account2.getAccountAddress()); + + // All accounts can be recovered from the same mnemonic + } +} +``` + +### Example 4: Message Signing and Verification + +```java +import com.aptoslabs.japtos.account.Ed25519Account; +import com.aptoslabs.japtos.core.crypto.Signature; + +public class MessageSigningExample { + public static void main(String[] args) throws Exception { + // Create account + Ed25519Account account = Ed25519Account.generate(); + + // Sign a message + String message = "Hello, Aptos Blockchain!"; + byte[] messageBytes = message.getBytes(); + Signature signature = account.sign(messageBytes); + + System.out.println("Message: " + message); + System.out.println("Signature: " + signature.toHex()); + + // Verify signature + boolean isValid = account.verifySignature(messageBytes, signature); + System.out.println("Signature valid: " + isValid); + + // Verify with wrong message fails + byte[] wrongMessage = "Different message".getBytes(); + boolean isInvalid = account.verifySignature(wrongMessage, signature); + System.out.println("Wrong message verified: " + isInvalid); // false + } +} +``` + +### Example 5: Checking Account Balance + +```java +import com.aptoslabs.japtos.types.AccountAddress; +import com.google.gson.JsonObject; + +public class BalanceCheck { + public static void main(String[] args) throws Exception { + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // Create and fund account + Ed25519Account account = Ed25519Account.generate(); + client.fundAccount(account.getAccountAddress(), 50_000_000); + + // Check APT balance + long balance = getAptBalance(client, account.getAccountAddress()); + System.out.println("Balance: " + balance + " octas"); + System.out.println("Balance: " + (balance / 100_000_000.0) + " APT"); + } + + private static long getAptBalance(AptosClient client, AccountAddress address) + throws Exception { + String resourceType = "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>"; + JsonObject resource = client.getAccountResource(address, resourceType); + return resource.getAsJsonObject("coin") + .get("value") + .getAsLong(); + } +} +``` + +### Example 6: Transaction Simulation + +```java +public class TransactionSimulation { + public static void main(String[] args) throws Exception { + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + Ed25519Account sender = Ed25519Account.generate(); + Ed25519Account receiver = Ed25519Account.generate(); + + client.fundAccount(sender.getAccountAddress(), 100_000_000); + + // Build transaction + ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") + ); + + TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), + Arrays.asList( + new TransactionArgument.AccountAddress(receiver.getAccountAddress()), + new TransactionArgument.U64(1_000_000L) + ) + ); + + RawTransaction rawTx = new RawTransaction( + sender.getAccountAddress(), + client.getAccountSequenceNumber(sender.getAccountAddress()), + payload, + 200000L, + 100L, + System.currentTimeMillis() / 1000 + 600, + client.getChainId() + ); + + // Simulate before submitting + SimulationResult simulation = client.simulateTransaction(rawTx, sender); + + System.out.println("Simulation results:"); + System.out.println("Success: " + simulation.isSuccess()); + System.out.println("Gas used: " + simulation.getGasUsed()); + System.out.println("VM status: " + simulation.getVmStatus()); + + if (simulation.isSuccess()) { + // Safe to submit + SignedTransaction signedTx = new SignedTransaction( + rawTx, + sender.signTransactionWithAuthenticator(rawTx) + ); + PendingTransaction pending = client.submitTransaction(signedTx); + System.out.println("Transaction submitted: " + pending.getHash()); + } else { + System.err.println("Simulation failed, not submitting"); + } + } +} +``` + +## Advanced Examples + +### Custom Module Interaction + +```java +// Call a custom module function +ModuleId customModule = new ModuleId( + AccountAddress.fromHex("0x123abc..."), // your module address + new Identifier("my_module") +); + +TransactionPayload payload = new EntryFunctionPayload( + customModule, + new Identifier("my_function"), + Arrays.asList( + // Type arguments (if function is generic) + new TypeTag.U64() + ), + Arrays.asList( + // Function arguments + new TransactionArgument.U64(100L), + new TransactionArgument.String("parameter") + ) +); +``` + +### Working with Different Networks + +```java +// Mainnet +AptosConfig mainnetConfig = AptosConfig.builder() + .network(AptosConfig.Network.MAINNET) + .build(); + +// Testnet +AptosConfig testnetConfig = AptosConfig.builder() + .network(AptosConfig.Network.TESTNET) + .build(); + +// Custom node +AptosConfig customConfig = AptosConfig.builder() + .fullNodeUrl("https://your-custom-node.com/v1") + .build(); +``` + +## Testing Best Practices + +1. **Always test on Devnet first** before deploying to Mainnet +2. **Use try-catch blocks** for error handling +3. **Implement timeouts** for transaction waiting +4. **Validate inputs** before building transactions +5. **Check simulation results** before submitting expensive transactions +6. **Keep private keys secure** - never hardcode them in source files + +## Helpful Resources + +- [SDK Test Suite](https://github.com/aptos-labs/japtos/tree/main/src/test) - Most comprehensive code examples +- [SDK Source Code](https://github.com/aptos-labs/japtos) - In-line comments and implementation details +- [Aptos REST API](https://fullnode.devnet.aptoslabs.com/v1/spec#/) - API endpoints used by the SDK +- [Move Documentation](/build/smart-contracts) - Understanding smart contracts + +## Related Documentation + +- [Quickstart](/build/sdks/java-sdk/quickstart) +- [Managing Accounts](/build/sdks/java-sdk/account) +- [Building Transactions](/build/sdks/java-sdk/building-transactions) +- [Java SDK Overview](/build/sdks/java-sdk) + diff --git a/src/content/docs/build/sdks/java-sdk/quickstart.mdx b/src/content/docs/build/sdks/java-sdk/quickstart.mdx new file mode 100644 index 00000000..b938717c --- /dev/null +++ b/src/content/docs/build/sdks/java-sdk/quickstart.mdx @@ -0,0 +1,291 @@ +--- +title: "Java SDK Quickstart" +description: "Get started with the Aptos Java SDK by creating accounts, funding them, and transferring APT tokens" +sidebar: + label: "Quickstart" +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + + + +This quickstart guide will walk you through setting up a Java project with the Aptos Java SDK and performing a simple APT token transfer. + + + 1. **Create a new Maven project** + + Create a new directory and initialize a Maven project: + + ```shellscript filename="Terminal" + mkdir aptos-java-quickstart + cd aptos-java-quickstart + ``` + + Create a `pom.xml` file with the following content: + + ```xml filename="pom.xml" + + + 4.0.0 + + com.example + aptos-quickstart + 1.0-SNAPSHOT + + + 11 + 11 + UTF-8 + + + + + github + https://maven.pkg.github.com/aptos-labs/japtos + + + + + + com.aptos-labs + japtos + 1.1.0 + + + + ``` + + 2. **Set up GitHub Packages authentication** + + Create or edit `~/.m2/settings.xml` and add your GitHub credentials: + + ```xml filename="~/.m2/settings.xml" + + + + github + YOUR_GITHUB_USERNAME + YOUR_GITHUB_TOKEN + + + + ``` + + + + 3. **Create the quickstart example** + + Create the directory structure and main file: + + ```shellscript filename="Terminal" + mkdir -p src/main/java/com/example + ``` + + Create `src/main/java/com/example/Quickstart.java`: + + ```java filename="src/main/java/com/example/Quickstart.java" + package com.example; + + import com.aptoslabs.japtos.account.Ed25519Account; + import com.aptoslabs.japtos.api.AptosConfig; + import com.aptoslabs.japtos.client.AptosClient; + import com.aptoslabs.japtos.transaction.*; + import com.aptoslabs.japtos.types.*; + import com.google.gson.JsonObject; + + import java.util.Arrays; + + public class Quickstart { + + public static void main(String[] args) { + try { + System.out.println("=== Aptos Java SDK Quickstart ===\n"); + + // 1. Set up the Aptos client + System.out.println("Setting up Aptos client..."); + AptosConfig config = AptosConfig.builder() + .network(AptosConfig.Network.DEVNET) + .build(); + AptosClient client = new AptosClient(config); + + // 2. Create accounts + System.out.println("\n=== Creating Accounts ==="); + Ed25519Account alice = Ed25519Account.generate(); + Ed25519Account bob = Ed25519Account.generate(); + + System.out.println("Alice's address: " + alice.getAccountAddress()); + System.out.println("Bob's address: " + bob.getAccountAddress()); + + // 3. Fund accounts + System.out.println("\n=== Funding Accounts ==="); + client.fundAccount(alice.getAccountAddress(), 100_000_000); + client.fundAccount(bob.getAccountAddress(), 1_000); + System.out.println("Accounts funded!"); + + // 4. Check initial balances + System.out.println("\n=== Initial Balances ==="); + long aliceBalance = getBalance(client, alice.getAccountAddress()); + long bobBalance = getBalance(client, bob.getAccountAddress()); + System.out.println("Alice's balance: " + aliceBalance + " octas"); + System.out.println("Bob's balance: " + bobBalance + " octas"); + + // 5. Build transfer transaction + System.out.println("\n=== Building Transaction ==="); + long transferAmount = 1_000_000L; // 0.01 APT + + ModuleId moduleId = new ModuleId( + AccountAddress.fromHex("0x1"), + new Identifier("aptos_account") + ); + + TransactionPayload payload = new EntryFunctionPayload( + moduleId, + new Identifier("transfer"), + Arrays.asList(), + Arrays.asList( + new TransactionArgument.AccountAddress(bob.getAccountAddress()), + new TransactionArgument.U64(transferAmount) + ) + ); + + // Get sequence number and chain ID + long sequenceNumber = client.getAccountSequenceNumber( + alice.getAccountAddress() + ); + int chainId = client.getChainId(); + + // Build raw transaction + RawTransaction rawTx = new RawTransaction( + alice.getAccountAddress(), + sequenceNumber, + payload, + 200000L, // maxGasAmount + 100L, // gasUnitPrice + System.currentTimeMillis() / 1000 + 3600, // expiration (1 hour) + chainId + ); + + // 6. Sign and submit transaction + System.out.println("Signing and submitting transaction..."); + SignedTransaction signedTx = new SignedTransaction( + rawTx, + alice.signTransactionWithAuthenticator(rawTx) + ); + + PendingTransaction pendingTx = client.submitTransaction(signedTx); + System.out.println("Transaction hash: " + pendingTx.getHash()); + + // 7. Wait for transaction to complete + System.out.println("Waiting for transaction..."); + Transaction completedTx = client.waitForTransaction(pendingTx.getHash()); + System.out.println("Transaction completed: " + completedTx.isSuccess()); + + // 8. Check final balances + System.out.println("\n=== Final Balances ==="); + long aliceFinalBalance = getBalance(client, alice.getAccountAddress()); + long bobFinalBalance = getBalance(client, bob.getAccountAddress()); + System.out.println("Alice's balance: " + aliceFinalBalance + " octas"); + System.out.println("Bob's balance: " + bobFinalBalance + " octas"); + + // Verify the transfer + System.out.println("\n=== Verification ==="); + System.out.println("Expected Bob's balance increase: " + transferAmount); + System.out.println("Actual Bob's balance increase: " + + (bobFinalBalance - bobBalance)); + System.out.println("Alice paid gas: " + + (aliceBalance - aliceFinalBalance - transferAmount) + " octas"); + + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + e.printStackTrace(); + } + } + + private static long getBalance(AptosClient client, AccountAddress address) + throws Exception { + String resourceType = "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>"; + JsonObject resource = client.getAccountResource(address, resourceType); + return resource.getAsJsonObject("coin") + .get("value") + .getAsLong(); + } + } + ``` + + 4. **Run the quickstart** + + Compile and run the example: + + ```shellscript filename="Terminal" + mvn compile + mvn exec:java -Dexec.mainClass="com.example.Quickstart" + ``` + + You should see output similar to: + + ``` + === Aptos Java SDK Quickstart === + + Setting up Aptos client... + + === Creating Accounts === + Alice's address: 0x1234... + Bob's address: 0x5678... + + === Funding Accounts === + Accounts funded! + + === Initial Balances === + Alice's balance: 100000000 octas + Bob's balance: 1000 octas + + === Building Transaction === + Signing and submitting transaction... + Transaction hash: 0xabc... + Waiting for transaction... + Transaction completed: true + + === Final Balances === + Alice's balance: 98998900 octas + Bob's balance: 1001000 octas + + === Verification === + Expected Bob's balance increase: 1000000 + Actual Bob's balance increase: 1000000 + Alice paid gas: 1100 octas + ``` + + +## Summary + +You just learned how to: + +1. Set up a Java project with the Aptos Java SDK +2. Connect to the Aptos network using `AptosClient` +3. Create accounts using `Ed25519Account.generate()` +4. Fund accounts on devnet using the faucet +5. Build a transaction with `RawTransaction` +6. Sign and submit a transaction +7. Wait for transaction completion +8. Query account resources and balances + +## Next Steps + +- Learn about [account management](/build/sdks/java-sdk/account) including multi-signature and HD wallets +- Explore [building transactions](/build/sdks/java-sdk/building-transactions) in depth +- Check out more [examples](/build/sdks/java-sdk/java-examples) in the SDK repository + + + diff --git a/src/content/nav/en.ts b/src/content/nav/en.ts index e84edd41..e0e080ce 100644 --- a/src/content/nav/en.ts +++ b/src/content/nav/en.ts @@ -26,6 +26,7 @@ const labels = { "build.group.sdks.dotnet-sdk.accounts": "Accounts", "build.group.sdks.dotnet-sdk.queries": "Queries", "build.group.sdks.dotnet-sdk.transactions": "Transactions", + "build.group.sdks.java-sdk": "Java SDK", "build.group.sdks.python-sdk": "Python SDK", "build.group.sdks.unity-sdk": "Unity SDK", "build.group.sdks.cpp-sdk": "C++ SDK",