@@ -23,55 +23,152 @@ Maven:
23
23
<dependency >
24
24
<groupId >com.algorand</groupId >
25
25
<artifactId >algosdk</artifactId >
26
- <version >1.5.1 </version >
26
+ <version >1.6.0 </version >
27
27
</dependency >
28
28
```
29
29
30
30
# Quickstart
31
31
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.
32
33
``` 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 ;
34
55
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
+ }
40
104
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
+ }
41
116
42
- public class Main {
117
+ // Wait for indexer to index the round.
118
+ Thread . sleep(5000 );
43
119
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" );
60
127
}
128
+
129
+ System . out. println(" Transaction received! \n " + transactions. toString());
61
130
}
62
131
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
+ }
75
172
}
76
173
```
77
174
0 commit comments