Skip to content

Commit 315d1d0

Browse files
committed
Merge branch 'release/2.6.0'
2 parents 6746909 + e3bae2e commit 315d1d0

28 files changed

+743
-19
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- run: mvn test
2525
integration-test:
2626
machine:
27-
image: "ubuntu-2204:2022.04.2"
27+
image: "ubuntu-2204:2022.10.2"
2828
resource_class: medium
2929
steps:
3030
- checkout

.test-env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Configs for testing repo download:
22
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
3-
SDK_TESTING_BRANCH="V2"
3+
SDK_TESTING_BRANCH="master"
44
SDK_TESTING_HARNESS="test-harness"
55

66
INSTALL_ONLY=0

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# 2.6.0
2+
3+
<!-- Release notes generated using configuration in .github/release.yml at release/2.6.0 -->
4+
5+
## What's Changed
6+
### Enhancements
7+
* Simulate: Support `fixSigners` option by @github-actions in https://github.com/algorand/java-algorand-sdk/pull/721
8+
* Incentives: Support heartbeat txn, Java 8 Min Version by @algorandskiy in https://github.com/algorand/java-algorand-sdk/pull/758
9+
10+
11+
**Full Changelog**: https://github.com/algorand/java-algorand-sdk/compare/2.5.0...2.6.0
12+
113
# 2.5.0
214

315
<!-- Release notes generated using configuration in .github/release.yml at release/2.5.0 -->

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Maven:
1919
<dependency>
2020
<groupId>com.algorand</groupId>
2121
<artifactId>algosdk</artifactId>
22-
<version>2.5.0</version>
22+
<version>2.6.0</version>
2323
</dependency>
2424
```
2525

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.algorand</groupId>
66
<artifactId>algosdk</artifactId>
7-
<version>2.5.0</version>
7+
<version>2.6.0</version>
88
<packaging>jar</packaging>
99

1010
<name>${project.groupId}:${project.artifactId}</name>
@@ -42,8 +42,8 @@
4242
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
4343

4444
<!-- Test sources at 1.8 to allow using JUnit5 -->
45-
<java.version>1.7</java.version>
46-
<java.release.version>7</java.release.version>
45+
<java.version>1.8</java.version>
46+
<java.release.version>8</java.release.version>
4747
<java.test.release.version>8</java.test.release.version>
4848

4949
<!-- github server corresponds to entry in ~/.m2/settings.xml -->
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.algorand.algosdk.transaction;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
6+
import com.algorand.algosdk.crypto.*;
7+
import com.fasterxml.jackson.annotation.JsonCreator;
8+
import com.fasterxml.jackson.annotation.JsonInclude;
9+
import com.fasterxml.jackson.annotation.JsonProperty;
10+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
11+
12+
13+
@JsonPropertyOrder(alphabetic = true)
14+
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
15+
public class HeartbeatProof implements Serializable {
16+
@JsonProperty("s")
17+
public Signature sig = new Signature();
18+
19+
@JsonProperty("p")
20+
public Ed25519PublicKey pk = new Ed25519PublicKey();
21+
22+
@JsonProperty("p2")
23+
public Ed25519PublicKey pk2 = new Ed25519PublicKey();
24+
25+
@JsonProperty("p1s")
26+
public Signature pk1Sig = new Signature();
27+
28+
@JsonProperty("p2s")
29+
public Signature pk2Sig = new Signature();
30+
31+
public HeartbeatProof() {}
32+
33+
public HeartbeatProof(
34+
Signature sig,
35+
Ed25519PublicKey pk,
36+
Ed25519PublicKey pk2,
37+
Signature pk1Sig,
38+
Signature pk2Sig
39+
) {
40+
this.sig = Objects.requireNonNull(sig, "sig must not be null");
41+
this.pk = Objects.requireNonNull(pk, "pk must not be null");
42+
this.pk2 = Objects.requireNonNull(pk2, "pk2 must not be null");
43+
this.pk1Sig = Objects.requireNonNull(pk1Sig, "pk1Sig must not be null");
44+
this.pk2Sig = Objects.requireNonNull(pk2Sig, "pk2Sig must not be null");
45+
}
46+
47+
@JsonCreator
48+
public HeartbeatProof(
49+
@JsonProperty("s") byte[] sig,
50+
@JsonProperty("p") byte[] pk,
51+
@JsonProperty("p2") byte[] pk2,
52+
@JsonProperty("p1s") byte[] pk1Sig,
53+
@JsonProperty("p2s") byte[] pk2Sig
54+
) {
55+
this.sig = new Signature(sig);
56+
this.pk = new Ed25519PublicKey(pk);
57+
this.pk2 = new Ed25519PublicKey(pk2);
58+
this.pk1Sig = new Signature(pk1Sig);
59+
this.pk2Sig = new Signature(pk2Sig);
60+
}
61+
62+
@Override
63+
public boolean equals(Object o) {
64+
if (this == o) return true;
65+
if (o == null || getClass() != o.getClass()) return false;
66+
HeartbeatProof that = (HeartbeatProof) o;
67+
return Objects.equals(sig, that.sig) &&
68+
Objects.equals(pk, that.pk) &&
69+
Objects.equals(pk2, that.pk2) &&
70+
Objects.equals(pk1Sig, that.pk1Sig) &&
71+
Objects.equals(pk2Sig, that.pk2Sig);
72+
}
73+
74+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.algorand.algosdk.transaction;
2+
3+
import java.io.Serializable;
4+
import java.math.BigInteger;
5+
import java.util.Arrays;
6+
import java.util.Objects;
7+
8+
import com.algorand.algosdk.crypto.*;
9+
import com.fasterxml.jackson.annotation.JsonCreator;
10+
import com.fasterxml.jackson.annotation.JsonInclude;
11+
import com.fasterxml.jackson.annotation.JsonProperty;
12+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
13+
14+
@JsonPropertyOrder(alphabetic = true)
15+
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
16+
public class HeartbeatTxnFields implements Serializable {
17+
@JsonProperty("a")
18+
public Address hbAddress = new Address();
19+
20+
@JsonProperty("prf")
21+
public HeartbeatProof hbProof = new HeartbeatProof();
22+
23+
@JsonProperty("sd")
24+
public byte[] hbSeed = new byte[32]; // committee.Seed
25+
26+
@JsonProperty("vid")
27+
public ParticipationPublicKey hbVoteID = new ParticipationPublicKey();
28+
29+
@JsonProperty("kd")
30+
public BigInteger hbKeyDilution = BigInteger.valueOf(0);
31+
32+
public HeartbeatTxnFields() {}
33+
34+
public HeartbeatTxnFields(
35+
Address hbAddress,
36+
HeartbeatProof hbProof,
37+
byte[] hbSeed,
38+
ParticipationPublicKey hbVoteID,
39+
BigInteger hbKeyDilution
40+
) {
41+
this.hbAddress = Objects.requireNonNull(hbAddress, "hbAddress must not be null");
42+
this.hbProof = Objects.requireNonNull(hbProof, "hbProof must not be null");
43+
this.hbVoteID = Objects.requireNonNull(hbVoteID, "hbVoteID must not be null");
44+
this.hbKeyDilution = Objects.requireNonNull(hbKeyDilution, "hbKeyDilution must not be null");
45+
if (hbSeed == null) {
46+
throw new NullPointerException("hbSeed must not be null");
47+
}
48+
System.arraycopy(hbSeed, 0, this.hbSeed, 0, this.hbSeed.length);
49+
}
50+
51+
@JsonCreator
52+
public HeartbeatTxnFields(
53+
@JsonProperty("a") byte[] hbAddress,
54+
@JsonProperty("prf") HeartbeatProof hbProof,
55+
@JsonProperty("sd") byte[] hbSeed,
56+
@JsonProperty("vid") byte[] hbVoteID,
57+
@JsonProperty("kd") BigInteger hbKeyDilution
58+
) {
59+
if (hbAddress != null) {
60+
this.hbAddress = new Address(hbAddress);
61+
}
62+
if (hbProof != null) {
63+
this.hbProof = hbProof;
64+
}
65+
if (hbSeed != null) {
66+
System.arraycopy(hbSeed, 0, this.hbSeed, 0, this.hbSeed.length);
67+
}
68+
if (hbVoteID != null) {
69+
this.hbVoteID = new ParticipationPublicKey(hbVoteID);
70+
}
71+
if (hbKeyDilution != null) {
72+
this.hbKeyDilution = hbKeyDilution;
73+
}
74+
}
75+
76+
@Override
77+
public boolean equals(Object o) {
78+
if (this == o) return true;
79+
if (o == null || getClass() != o.getClass()) return false;
80+
HeartbeatTxnFields that = (HeartbeatTxnFields) o;
81+
return hbAddress.equals(that.hbAddress) &&
82+
hbProof.equals(that.hbProof) &&
83+
Arrays.equals(hbSeed, that.hbSeed) &&
84+
hbVoteID.equals(that.hbVoteID) &&
85+
hbKeyDilution.equals(that.hbKeyDilution);
86+
}
87+
}

src/main/java/com/algorand/algosdk/transaction/Transaction.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ public class Transaction implements Serializable {
175175
@JsonProperty("spmsg")
176176
public Map<String,Object> stateProofMessage = null;
177177

178+
@JsonProperty("hb")
179+
public HeartbeatTxnFields heartbeatFields = new HeartbeatTxnFields();
180+
178181
/**
179182
* Helper for Jackson conversion.
180183
*/
@@ -238,7 +241,9 @@ private Transaction(@JsonProperty("type") Type type,
238241
@JsonProperty("apid") Long applicationId,
239242
@JsonProperty("apls") StateSchema localStateSchema,
240243
@JsonProperty("apsu") byte[] clearStateProgram,
241-
@JsonProperty("apep") Long extraPages
244+
@JsonProperty("apep") Long extraPages,
245+
// heartbeat fields
246+
@JsonProperty("hb") HeartbeatTxnFields heartbeatFields
242247
) throws IOException {
243248
this(
244249
type,
@@ -289,7 +294,8 @@ private Transaction(@JsonProperty("type") Type type,
289294
applicationId,
290295
localStateSchema,
291296
clearStateProgram == null ? null : new TEALProgram(clearStateProgram),
292-
extraPages
297+
extraPages,
298+
heartbeatFields
293299
);
294300
}
295301

@@ -348,7 +354,8 @@ private Transaction(
348354
Long applicationId,
349355
StateSchema localStateSchema,
350356
TEALProgram clearStateProgram,
351-
Long extraPages
357+
Long extraPages,
358+
HeartbeatTxnFields heartbeatFields
352359
) {
353360
if (type != null) this.type = type;
354361
if (sender != null) this.sender = sender;
@@ -393,6 +400,7 @@ private Transaction(
393400
if (localStateSchema != null) this.localStateSchema = localStateSchema;
394401
if (clearStateProgram != null) this.clearStateProgram = clearStateProgram;
395402
if (extraPages != null) this.extraPages = extraPages;
403+
if (heartbeatFields != null) this.heartbeatFields = heartbeatFields;
396404
}
397405

398406
// Used by Jackson to determine "default" values.
@@ -433,7 +441,8 @@ public enum Type {
433441
AssetTransfer("axfer"),
434442
AssetFreeze("afrz"),
435443
ApplicationCall("appl"),
436-
StateProof("stpf");
444+
StateProof("stpf"),
445+
Heartbeat("hb");
437446

438447
private static Map<String, Type> namesMap = new HashMap<String, Type>(6);
439448

@@ -604,7 +613,8 @@ public boolean equals(Object o) {
604613
freezeState == that.freezeState &&
605614
rekeyTo.equals(that.rekeyTo) &&
606615
extraPages.equals(that.extraPages) &&
607-
boxReferences.equals(that.boxReferences);
616+
boxReferences.equals(that.boxReferences) &&
617+
heartbeatFields.equals(that.heartbeatFields);
608618
}
609619

610620
/**

src/main/java/com/algorand/algosdk/v2/client/algod/AccountInformation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
/**
14-
* Given a specific account public key, this call returns the accounts status,
14+
* Given a specific account public key, this call returns the account's status,
1515
* balance and spendable amounts
1616
* /v2/accounts/{address}
1717
*/
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.algorand.algosdk.v2.client.algod;
2+
3+
import com.algorand.algosdk.v2.client.common.Client;
4+
import com.algorand.algosdk.v2.client.common.HttpMethod;
5+
import com.algorand.algosdk.v2.client.common.Query;
6+
import com.algorand.algosdk.v2.client.common.QueryData;
7+
import com.algorand.algosdk.v2.client.common.Response;
8+
import com.algorand.algosdk.v2.client.model.BlockHeaderResponse;
9+
10+
11+
/**
12+
* Get the block header for the block on the given round.
13+
* /v2/blocks/{round}/header
14+
*/
15+
public class GetBlockHeader extends Query {
16+
17+
private Long round;
18+
19+
/**
20+
* @param round The round from which to fetch block header information.
21+
*/
22+
public GetBlockHeader(Client client, Long round) {
23+
super(client, new HttpMethod("get"));
24+
addQuery("format", "msgpack");
25+
this.round = round;
26+
}
27+
28+
/**
29+
* Execute the query.
30+
* @return the query response object.
31+
* @throws Exception
32+
*/
33+
@Override
34+
public Response<BlockHeaderResponse> execute() throws Exception {
35+
Response<BlockHeaderResponse> resp = baseExecute();
36+
resp.setValueType(BlockHeaderResponse.class);
37+
return resp;
38+
}
39+
40+
/**
41+
* Execute the query with custom headers, there must be an equal number of keys and values
42+
* or else an error will be generated.
43+
* @param headers an array of header keys
44+
* @param values an array of header values
45+
* @return the query response object.
46+
* @throws Exception
47+
*/
48+
@Override
49+
public Response<BlockHeaderResponse> execute(String[] headers, String[] values) throws Exception {
50+
Response<BlockHeaderResponse> resp = baseExecute(headers, values);
51+
resp.setValueType(BlockHeaderResponse.class);
52+
return resp;
53+
}
54+
55+
protected QueryData getRequestString() {
56+
if (this.round == null) {
57+
throw new RuntimeException("round is not set. It is a required parameter.");
58+
}
59+
addPathSegment(String.valueOf("v2"));
60+
addPathSegment(String.valueOf("blocks"));
61+
addPathSegment(String.valueOf(round));
62+
addPathSegment(String.valueOf("header"));
63+
64+
return qd;
65+
}
66+
}

0 commit comments

Comments
 (0)