Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
dikel committed Sep 19, 2023
2 parents e4669a9 + cf1c1e3 commit 0e52435
Show file tree
Hide file tree
Showing 20 changed files with 429 additions and 93 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 2.29.0

### Added
- `populateAccountEvmAddress` and `populateAccountEvmAddressAsync` to `AccountId`

### Fixed
- duplicate transaction IDs at high TPS (>25K)
- android compatibility issues

### Changed
- GRPC configurations

## 2.28.0

### Added
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Select _one_ of the following depending on your target platform.

```groovy
implementation 'com.hedera.hashgraph:sdk:2.28.0'
implementation 'com.hedera.hashgraph:sdk:2.29.0'
```

Select _one_ of the following to provide the gRPC implementation.
Expand Down Expand Up @@ -56,7 +56,7 @@ Select _one_ of the following depending on your target platform.
<dependency>
<groupId>com.hedera.hashgraph</groupId>
<artifactId>sdk</artifactId>
<version>2.28.0</version>
<version>2.29.0</version>
</dependency>
```

Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ plugins {

// Gradle plugin to discover dependency updates
// <https://github.com/ben-manes/gradle-versions-plugin>
id "com.github.ben-manes.versions" version "0.47.0"
id "com.github.ben-manes.versions" version "0.48.0"

id "jacoco"
id "org.sonarqube" version "4.3.0.3225"
id "org.sonarqube" version "4.3.1.3277"

id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
}
Expand All @@ -28,10 +28,10 @@ allprojects {
dependencies {
// https://github.com/google/error-prone
// https://errorprone.info/
errorprone "com.google.errorprone:error_prone_core:2.19.1"
errorprone "com.google.errorprone:error_prone_core:2.21.1"

// https://github.com/uber/NullAway
errorprone "com.uber.nullaway:nullaway:0.10.11"
errorprone "com.uber.nullaway:nullaway:0.10.14"

// https://github.com/grpc/grpc-java-api-checker
errorprone "io.grpc:grpc-java-api-checker:1.1.0"
Expand Down
2 changes: 1 addition & 1 deletion example-android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

implementation 'com.hedera.hashgraph:sdk:2.28.0'
implementation 'com.hedera.hashgraph:sdk:2.29.0'

implementation 'org.slf4j:slf4j-simple:2.0.7'
implementation 'io.grpc:grpc-okhttp:1.49.2'
Expand Down
4 changes: 2 additions & 2 deletions example-android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.9.0'
ext.kotlin_version = '1.9.10'

repositories {
google()
Expand All @@ -10,7 +10,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
classpath 'com.android.tools.build:gradle:8.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.quittle:android-emulator-plugin:0.4.5'

Expand Down
6 changes: 3 additions & 3 deletions examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ dependencies {
implementation project(":sdk")

implementation "com.google.code.gson:gson:2.10.1"
implementation "org.slf4j:slf4j-simple:2.0.7"
implementation "io.grpc:grpc-netty-shaded:1.56.1"
implementation "org.slf4j:slf4j-simple:2.0.9"
implementation "io.grpc:grpc-netty-shaded:1.57.2"
implementation "io.github.cdimascio:java-dotenv:5.3.1"
implementation "com.google.errorprone:error_prone_core:2.19.1"
implementation "com.google.errorprone:error_prone_core:2.21.1"
}

tasks.addRule("Pattern: run<Example>: Runs an example.") { String taskName ->
Expand Down
28 changes: 14 additions & 14 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
id "signing"
id "maven-publish"
id "com.google.protobuf" version "0.9.4"
id "com.github.spotbugs" version "5.0.14"
id "com.github.spotbugs" version "5.1.3"
}

apply from: "../version.gradle"
Expand Down Expand Up @@ -32,42 +32,42 @@ dependencies {
implementation group: 'com.github.spotbugs', name: 'spotbugs-annotations', version: '4.7.3'

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15to18
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.75'
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.76'

// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15to18
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: '1.75'
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: '1.76'

// https://mvnrepository.com/artifact/org.slf4j/slf4j-api
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation 'org.slf4j:slf4j-api:2.0.9'

implementation "io.grpc:grpc-core:1.57.0"
implementation "io.grpc:grpc-stub:1.56.1"
implementation "io.grpc:grpc-core:1.57.2"
implementation "io.grpc:grpc-stub:1.58.0"

implementation "com.google.code.gson:gson:2.10.1"
implementation 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'com.esaulpaugh:headlong:9.3.0'
implementation 'com.esaulpaugh:headlong:10.0.0'

testImplementation "org.assertj:assertj-core:3.24.2"
testImplementation "io.github.json-snapshot:json-snapshot:1.0.17"
testImplementation "org.junit.jupiter:junit-jupiter-engine:5.10.0"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.10.0"

testRuntimeOnly "org.slf4j:slf4j-simple:2.0.7"
testRuntimeOnly "io.grpc:grpc-netty-shaded:1.56.1"
testRuntimeOnly 'org.slf4j:slf4j-nop:2.0.7'
testRuntimeOnly "org.slf4j:slf4j-simple:2.0.9"
testRuntimeOnly "io.grpc:grpc-netty-shaded:1.57.2"
testRuntimeOnly 'org.slf4j:slf4j-nop:2.0.9'

integrationTestRuntimeOnly 'io.grpc:grpc-netty-shaded:1.56.1'
integrationTestRuntimeOnly 'org.slf4j:slf4j-nop:2.0.7'
integrationTestRuntimeOnly 'io.grpc:grpc-netty-shaded:1.57.2'
integrationTestRuntimeOnly 'org.slf4j:slf4j-nop:2.0.9'
}

// https://github.com/google/protobuf-gradle-plugin
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.23.4"
artifact = "com.google.protobuf:protoc:3.24.3"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.57.0"
artifact = "io.grpc:protoc-gen-grpc-java:1.58.0"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,55 @@ void canPopulateAccountIdNumAsync() throws Exception {

assertThat(newAccountId.num).isEqualTo(accountId.num);
}

@Test
@DisplayName("Can populate AccountId evm address from mirror node (using sync method)")
void canPopulateAccountIdEvmAddressSync() throws Exception {
var testEnv = new IntegrationTestEnv(1);

var privateKey = PrivateKey.generateECDSA();
var publicKey = privateKey.getPublicKey();

var evmAddress = publicKey.toEvmAddress();
var evmAddressAccount = AccountId.fromEvmAddress(evmAddress);

var tx = new TransferTransaction().addHbarTransfer(evmAddressAccount, new Hbar(1))
.addHbarTransfer(testEnv.operatorId, new Hbar(-1)).execute(testEnv.client);

var receipt = new TransactionReceiptQuery().setTransactionId(tx.transactionId).setIncludeChildren(true)
.execute(testEnv.client);

var newAccountId = receipt.children.get(0).accountId;

Thread.sleep(5000);
var accountId = newAccountId.populateAccountEvmAddress(testEnv.client);

assertThat(evmAddressAccount.evmAddress).isEqualTo(accountId.evmAddress);
}

@Test
@DisplayName("Can populate AccountId evm address from mirror node (using async method)")
void canPopulateAccountIdEvmAddressAsync() throws Exception {
var testEnv = new IntegrationTestEnv(1);

var privateKey = PrivateKey.generateECDSA();
var publicKey = privateKey.getPublicKey();

var evmAddress = publicKey.toEvmAddress();
var evmAddressAccount = AccountId.fromEvmAddress(evmAddress);

var tx = new TransferTransaction().addHbarTransfer(evmAddressAccount, new Hbar(1))
.addHbarTransfer(testEnv.operatorId, new Hbar(-1)).execute(testEnv.client);

var receipt = new TransactionReceiptQuery().setTransactionId(tx.transactionId).setIncludeChildren(true)
.execute(testEnv.client);

var newAccountId = receipt.children.get(0).accountId;

Thread.sleep(5000);
var accountId = newAccountId.populateAccountEvmAddressAsync(testEnv.client).get();

assertThat(evmAddressAccount.evmAddress).isEqualTo(accountId.evmAddress);
}

}
30 changes: 30 additions & 0 deletions sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,36 @@ public CompletableFuture<AccountId> populateAccountNumAsync(Client client) {
this.evmAddress));
}

/**
* Populates `evmAddress` field of the `AccountId` extracted from the Mirror Node.
* Sync version
*
* @param client
* @return populated AccountId instance
*/
public AccountId populateAccountEvmAddress(Client client) throws ExecutionException, InterruptedException {
return populateAccountEvmAddressAsync(client).get();
}

/**
* Populates `evmAddress` field of the `AccountId` extracted from the Mirror Node.
* Async version
*
* @param client
* @return populated AccountId instance
*/
public CompletableFuture<AccountId> populateAccountEvmAddressAsync(Client client) {
return EntityIdHelper.getEvmAddressFromMirrorNodeAsync(client, num)
.thenApply(evmAddressFromMirrorNode ->
new AccountId(
this.shard,
this.realm,
this.num,
this.checksum,
this.aliasKey,
evmAddressFromMirrorNode));
}

/**
* @param client to validate against
* @throws BadEntityIdException if entity ID is formatted poorly
Expand Down
6 changes: 4 additions & 2 deletions sdk/src/main/java/com/hedera/hashgraph/sdk/AccountInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*/
package com.hedera.hashgraph.sdk;

import static java.util.stream.Collectors.toList;

import com.google.common.base.MoreObjects;
import com.google.protobuf.InvalidProtocolBufferException;
import com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse;
Expand Down Expand Up @@ -261,7 +263,7 @@ static AccountInfo fromProtobuf(CryptoGetInfoResponse.AccountInfo accountInfo) {

var liveHashes = Arrays.stream(accountInfo.getLiveHashesList().toArray())
.map((liveHash) -> LiveHash.fromProtobuf((com.hedera.hashgraph.sdk.proto.LiveHash) liveHash))
.toList();
.collect(toList());

Map<TokenId, TokenRelationship> relationships = new HashMap<>();

Expand Down Expand Up @@ -317,7 +319,7 @@ public static AccountInfo fromBytes(byte[] bytes) throws InvalidProtocolBufferEx
CryptoGetInfoResponse.AccountInfo toProtobuf() {
var hashes = Arrays.stream(liveHashes.toArray())
.map((liveHash) -> ((LiveHash) liveHash).toProtobuf())
.toList();
.collect(toList());

var accountInfoBuilder = CryptoGetInfoResponse.AccountInfo.newBuilder()
.setAccountID(accountId.toProtobuf())
Expand Down
14 changes: 13 additions & 1 deletion sdk/src/main/java/com/hedera/hashgraph/sdk/Delayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package com.hedera.hashgraph.sdk;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
Expand All @@ -33,6 +35,12 @@
final class Delayer {
private static final Logger logger = LoggerFactory.getLogger(Delayer.class);

private static final ScheduledExecutorService SCHEDULER = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});

private static final Duration MIN_DELAY = Duration.ofMillis(500);

/**
Expand Down Expand Up @@ -67,6 +75,10 @@ static CompletableFuture<Void> delayFor(long milliseconds, Executor executor) {
return CompletableFuture.runAsync(
() -> {
},
CompletableFuture.delayedExecutor(milliseconds, TimeUnit.MILLISECONDS, executor));
delayedExecutor(milliseconds, TimeUnit.MILLISECONDS, executor));
}

private static Executor delayedExecutor(long delay, TimeUnit unit, Executor executor) {
return r -> SCHEDULER.schedule(() -> executor.execute(r), delay, unit);
}
}
25 changes: 25 additions & 0 deletions sdk/src/main/java/com/hedera/hashgraph/sdk/EntityIdHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,22 @@ public static CompletableFuture<Long> getAccountNumFromMirrorNodeAsync(Client cl
parseNumFromMirrorNodeResponse(response, "account"));
}

/**
* Get EvmAddress from mirror node using account num.
*
* @param client
* @param num
* @return
* @throws IOException
* @throws InterruptedException
*/
public static CompletableFuture<EvmAddress> getEvmAddressFromMirrorNodeAsync(Client client, long num) {
String apiEndpoint = "/accounts/" + num;
return performQueryToMirrorNodeAsync(client, apiEndpoint)
.thenApply(response ->
EvmAddress.fromString(parseEvmAddressFromMirrorNodeResponse(response, "evm_address")));
}

/**
* Get ContractId num from mirror node using evm address.
*
Expand Down Expand Up @@ -350,6 +366,15 @@ private static long parseNumFromMirrorNodeResponse(String responseBody, String m
return Long.parseLong(num.substring(num.lastIndexOf(".") + 1));
}

private static String parseEvmAddressFromMirrorNodeResponse(String responseBody, String memberName) {
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = jsonParser.parse(responseBody).getAsJsonObject();

String evmAddress = jsonObject.get(memberName).getAsString();

return evmAddress.substring(evmAddress.lastIndexOf(".") + 1);
}

@FunctionalInterface
interface WithIdNums<R> {
R apply(long shard, long realm, long num, @Nullable String checksum);
Expand Down
Loading

0 comments on commit 0e52435

Please sign in to comment.