@@ -23,55 +23,152 @@ Maven:
2323<dependency >
2424 <groupId >com.algorand</groupId >
2525 <artifactId >algosdk</artifactId >
26- <version >1.5.1 </version >
26+ <version >1.6.0 </version >
2727</dependency >
2828```
2929
3030# Quickstart
3131
32+ This program connects to a running [ sandbox] ( https://github.com/algorand/sandbox ) private network, creates a payment transaction between two of the accounts, signs it with kmd, and reads result from Indexer.
3233``` java
33- package com.algorand.algosdk.example ;
34+ import com.algorand.algosdk.account.Account ;
35+ import com.algorand.algosdk.crypto.Address ;
36+ import com.algorand.algosdk.kmd.client.ApiException ;
37+ import com.algorand.algosdk.kmd.client.KmdClient ;
38+ import com.algorand.algosdk.kmd.client.api.KmdApi ;
39+ import com.algorand.algosdk.kmd.client.model.* ;
40+ import com.algorand.algosdk.transaction.SignedTransaction ;
41+ import com.algorand.algosdk.transaction.Transaction ;
42+ import com.algorand.algosdk.util.Encoder ;
43+ import com.algorand.algosdk.v2.client.common.AlgodClient ;
44+ import com.algorand.algosdk.v2.client.common.IndexerClient ;
45+ import com.algorand.algosdk.v2.client.common.Response ;
46+ import com.algorand.algosdk.v2.client.model.PendingTransactionResponse ;
47+ import com.algorand.algosdk.v2.client.model.PostTransactionsResponse ;
48+ import com.algorand.algosdk.v2.client.model.TransactionsResponse ;
49+
50+ import java.io.IOException ;
51+ import java.security.NoSuchAlgorithmException ;
52+ import java.util.ArrayList ;
53+ import java.util.Arrays ;
54+ import java.util.List ;
3455
35- import com.algorand.algosdk.algod.client.AlgodClient ;
36- import com.algorand.algosdk.algod.client.ApiException ;
37- import com.algorand.algosdk.algod.client.api.AlgodApi ;
38- import com.algorand.algosdk.algod.client.auth.ApiKeyAuth ;
39- import com.algorand.algosdk.algod.client.model.NodeStatus ;
56+ public class Main {
57+ private static String token = " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;
58+ private static KmdApi kmd = null ;
59+
60+ public static void main (String [] args ) throws Exception {
61+ // Initialize algod/indexer v2 clients.
62+ AlgodClient algod = new AlgodClient (" http://localhost" , 4001 , token);
63+ IndexerClient indexer = new IndexerClient (" http://localhost" , 8980 );
64+
65+ // Initialize KMD v1 client
66+ KmdClient kmdClient = new KmdClient ();
67+ kmdClient. setBasePath(" http://localhost:4002" );
68+ kmdClient. setApiKey(token);
69+ kmd = new KmdApi (kmdClient);
70+
71+ // Get accounts from sandbox.
72+ String walletHandle = getDefaultWalletHandle();
73+ List<Address > accounts = getWalletAccounts(walletHandle);
74+
75+ // Create a payment transaction
76+ Transaction tx1 = Transaction . PaymentTransactionBuilder()
77+ .lookupParams(algod) // lookup fee, firstValid, lastValid
78+ .sender(accounts. get(0 ))
79+ .receiver(accounts. get(1 ))
80+ .amount(1000000 )
81+ .noteUTF8(" test transaction!" )
82+ .build();
83+
84+ // Sign with KMD
85+ SignedTransaction stx1a = signTransactionWithKMD(tx1, walletHandle);
86+ byte [] stx1aBytes = Encoder . encodeToMsgPack(stx1a);
87+
88+ // Sign with private key
89+ byte [] privateKey = lookupPrivateKey(accounts. get(0 ), walletHandle);
90+ Account account = new Account (privateKey);
91+ SignedTransaction stx1b = account. signTransaction(tx1);
92+ byte [] stx1bBytes = Encoder . encodeToMsgPack(stx1b);
93+
94+ // KMD and signing directly should both be the same.
95+ if (! Arrays . equals(stx1aBytes, stx1bBytes)) {
96+ throw new RuntimeException (" KMD disagrees with the manual signature!" );
97+ }
98+
99+ // Send transaction
100+ Response<PostTransactionsResponse > post = algod. RawTransaction (). rawtxn(stx1aBytes). execute();
101+ if (! post. isSuccessful()) {
102+ throw new RuntimeException (" Failed to post transaction" );
103+ }
40104
105+ // Wait for confirmation
106+ boolean done = false ;
107+ while (! done) {
108+ Response<PendingTransactionResponse > txInfo = algod. PendingTransactionInformation (post. body(). txId). execute();
109+ if (! txInfo. isSuccessful()) {
110+ throw new RuntimeException (" Failed to check on tx progress" );
111+ }
112+ if (txInfo. body(). confirmedRound != null ) {
113+ done = true ;
114+ }
115+ }
41116
42- public class Main {
117+ // Wait for indexer to index the round.
118+ Thread . sleep(5000 );
43119
44- public static void main (String args []) throws Exception {
45- final String ALGOD_API_ADDR = " http://localhost:8080" ;
46- final String ALGOD_API_TOKEN = " d6f33a522f465ff12f0d263f2c3b707ac2f560bacad4d859914ada7e827902b3" ;
47-
48- AlgodClient client = new AlgodClient ();
49- client. setBasePath(ALGOD_API_ADDR );
50- ApiKeyAuth api_key = (ApiKeyAuth ) client. getAuthentication(" api_key" );
51- api_key. setApiKey(ALGOD_API_TOKEN );
52-
53- AlgodApi algodApiInstance = new AlgodApi (client);
54- try {
55- NodeStatus status = algodApiInstance. getStatus();
56- System . out. println(" Algorand network status: " + status);
57- } catch (ApiException e) {
58- System . err. println(" Exception when calling algod#getStatus" );
59- e. printStackTrace();
120+ // Query indexer for the transaction
121+ Response<TransactionsResponse > transactions = indexer. searchForTransactions()
122+ .txid(post. body(). txId)
123+ .execute();
124+
125+ if (! transactions. isSuccessful()) {
126+ throw new RuntimeException (" Failed to lookup transaction" );
60127 }
128+
129+ System . out. println(" Transaction received! \n " + transactions. toString());
61130 }
62131
63- }
64- ```
65- This prints:
66- ```
67- Algorand network status: class NodeStatus {
68- catchupTime: 0
69- lastConsensusVersion: v4
70- lastRound: 260318
71- nextConsensusVersion: v4
72- nextConsensusVersionRound: 260319
73- nextConsensusVersionSupported: true
74- timeSinceLastRound: 3620331759
132+ public static SignedTransaction signTransactionWithKMD (Transaction tx , String walletHandle ) throws IOException , ApiException {
133+ SignTransactionRequest req = new SignTransactionRequest ();
134+ req. transaction(Encoder . encodeToMsgPack(tx));
135+ req. setWalletHandleToken(walletHandle);
136+ req. setWalletPassword(" " );
137+ byte [] stxBytes = kmd. signTransaction(req). getSignedTransaction();
138+ return Encoder . decodeFromMsgPack(stxBytes, SignedTransaction . class);
139+ }
140+
141+ public static byte [] lookupPrivateKey (Address addr , String walletHandle ) throws ApiException {
142+ ExportKeyRequest req = new ExportKeyRequest ();
143+ req. setAddress(addr. toString());
144+ req. setWalletHandleToken(walletHandle);
145+ req. setWalletPassword(" " );
146+ return kmd. exportKey(req). getPrivateKey();
147+ }
148+
149+ public static String getDefaultWalletHandle () throws ApiException {
150+ for (APIV1Wallet w : kmd. listWallets(). getWallets()) {
151+ if (w. getName(). equals(" unencrypted-default-wallet" )) {
152+ InitWalletHandleTokenRequest tokenreq = new InitWalletHandleTokenRequest ();
153+ tokenreq. setWalletId(w. getId());
154+ tokenreq. setWalletPassword(" " );
155+ return kmd. initWalletHandleToken(tokenreq). getWalletHandleToken();
156+ }
157+ }
158+ throw new RuntimeException (" Default wallet not found." );
159+ }
160+
161+ public static List<Address > getWalletAccounts (String walletHandle ) throws ApiException , NoSuchAlgorithmException {
162+ List<Address > accounts = new ArrayList<> ();
163+
164+ ListKeysRequest keysRequest = new ListKeysRequest ();
165+ keysRequest. setWalletHandleToken(walletHandle);
166+ for (String addr : kmd. listKeysInWallet(keysRequest). getAddresses()) {
167+ accounts. add(new Address (addr));
168+ }
169+
170+ return accounts;
171+ }
75172}
76173```
77174
0 commit comments