Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
900 changes: 447 additions & 453 deletions docs/sdk/MIGRATING_V1.md

Large diffs are not rendered by default.

744 changes: 526 additions & 218 deletions docs/sdk/SDK_ANATOMY.md

Large diffs are not rendered by default.

104 changes: 49 additions & 55 deletions docs/sdk/developer-guide.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,56 @@
## JVM
# Java SDK Setup and Maintenance

JDK 17 is required. The Temurin builds of [Eclipse Adoptium](https://adoptium.net/) are strongly recommended.
This guide provides instructions for setting up, building, testing, and maintaining the Java SDK project. It covers JVM requirements, build processes, testing, dependency management, and file updates to ensure a smooth development experience.

## Setup
## JVM Requirements

> Note that the below `./gradlew` commands should be run from the root of the project.
JDK 17 is required. The Temurin builds from Eclipse Adoptium are strongly recommended.

This project uses the
[Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions)
Gradle setup. More details on how to work with the project can be found in the
[documentation](https://github.com/hiero-ledger/hiero-gradle-conventions#build).
## Setup Instructions

### Building
Note that all `./gradlew` commands should be run from the root of the project.

This project uses the Hiero Gradle Conventions for its Gradle setup. For more details on working with the project, refer to the documentation.

### Building the Project

To build the project, run:

```sh
./gradlew assemble
```

### Unit Tests
### Running Unit Tests

To execute unit tests for the SDK, run:

```sh
./gradlew :sdk:test
```

### Integration Tests
### Running Integration Tests

> The tests are only executed if the configuration is provided.
> That's why we need to pass the configuration file at the beginning of the command.
Integration tests are only executed if the required configuration is provided. Pass the configuration file or properties at the start of the command.

#### Using Gradle properties
#### Using Gradle Properties

`OPERATOR_ID`, `OPERATOR_KEY` and `HEDERA_NETWORK` must be passed as Gradle properties (`-P` parameters).\
`HEDERA_NETWORK` can be set to `localhost`, `testnet` or `previewnet`.
Provide `OPERATOR_ID`, `OPERATOR_KEY`, and `HEDERA_NETWORK` as Gradle properties using `-P` parameters. `HEDERA_NETWORK` can be set to `localhost`, `testnet`, or `previewnet`.

```sh
./gradlew :sdk:testIntegration -POPERATOR_ID="<shard.realm.num>" -POPERATOR_KEY="<PrivateKey>" -PHEDERA_NETWORK="<network>"
./gradlew :sdk:testIntegration -POPERATOR_ID="" -POPERATOR_KEY="" -PHEDERA_NETWORK=""
```

#### Using configuration file
#### Using a Configuration File

```sh
./gradlew :sdk:testIntegration -PCONFIG_FILE="<ConfigurationFilePath>"
./gradlew :sdk:testIntegration -PCONFIG_FILE=""
```

An example configuration file can be found in the repo here:
[sdk/src/test/resources/client-config-with-operator.json](../../sdk/src/test/resources/client-config-with-operator.json)
An example configuration file is available in the repository at: sdk/src/test/resources/client-config-with-operator.json.

**Running against the local network**
**Running Against a Local Network**

The format of the configuration file should be as follows:
Use a configuration file in this format:

```json
{
Expand All @@ -63,12 +65,11 @@ The format of the configuration file should be as follows:
"privateKey": "0xa608e2130a0a3cb34f86e757303c862bee353d9ab77ba4387ec084f881d420d4"
}
}

```

**Running against remote networks**
**Running Against Remote Networks**

The format of the configuration file should be as follows:
Use a configuration file in this format:

```json
{
Expand All @@ -80,78 +81,71 @@ The format of the configuration file should be as follows:
}
```

`HEDERA_NETWORK` can be set to `testnet`, `previewnet` or `mainnet`.
`HEDERA_NETWORK` can be set to `testnet`, `previewnet`, or `mainnet`.

#### Running individual test classes or functions
#### Running Individual Test Classes or Functions

Running test class:
To run a specific test class:

```sh
./gradlew :sdk:testIntegration -POPERATOR_ID="<shard.realm.num>" -POPERATOR_KEY="<PrivateKey>" -PHEDERA_NETWORK="testnet" --tests "<TestClass>"
./gradlew :sdk:testIntegration -POPERATOR_ID="" -POPERATOR_KEY="" -PHEDERA_NETWORK="testnet" --tests ""
```

Running test function:
To run a specific test function:

```sh
./gradlew :sdk:testIntegration -POPERATOR_ID="<shard.realm.num>" -POPERATOR_KEY="<PrivateKey>" -PHEDERA_NETWORK="testnet" --tests "<TestClass.functionName>"
./gradlew :sdk:testIntegration -POPERATOR_ID="" -POPERATOR_KEY="" -PHEDERA_NETWORK="testnet" --tests ""
```

#### Running with Intellij IDEA
#### Running with IntelliJ IDEA

1. Create a new Gradle run configuration (easiest way is to run test class or individual test function from the IDE).
2. Update "Run" configuration to pass the required Gradle properties (`OPERATOR_ID`, `OPERATOR_KEY` and `HEDERA_NETWORK`).
<img src="../assets/intellij-integration-tests.png">
1. Create a new Gradle run configuration (the easiest way is to run a test class or individual test function directly from the IDE).
2. Update the "Run" configuration to pass the required Gradle properties (`OPERATOR_ID`, `OPERATOR_KEY`, and `HEDERA_NETWORK`).

## Managing dependencies
## Managing Dependencies

This project uses a combination of Java Modules (JPMS) and Gradle to define and manage dependencies to 3rd party
libraries. In this structure, dependencies of the SDK are defined in
[sdk/src/main/java/module-info.java](../../sdk/src/main/java/module-info.java) (which is mirrored in
[sdk-full/src/main/java/module-info.java](../../sdk-full/src/main/java/module-info.java)).
Running `./gradlew qualityGate` contains a _dependency scope check_ that makes sure that both files are in sync.
Versions of 3rd party dependencies are defined in
[hiero-dependency-versions/build.gradle.kts](../../hiero-dependency-versions/build.gradle.kts).
More details about how to add/modify dependencies are found in the Hiero Gradle Conventions documentation on
[Defining modules and dependencies](https://github.com/hiero-ledger/hiero-gradle-conventions#modules).
This project uses a combination of Java Modules (JPMS) and Gradle to define and manage dependencies to third-party libraries. Dependencies for the SDK are defined in sdk/src/main/java/module-info.java (mirrored in sdk-full/src/main/java/module-info.java). Running `./gradlew qualityGate` includes a dependency scope check to ensure both files are in sync. Versions of third-party dependencies are defined in hiero-dependency-versions/build.gradle.kts. For more details on adding or modifying dependencies, see the Hiero Gradle Conventions documentation on defining modules and dependencies.

## Maintaining generated files
## Maintaining Generated Files

> Note that the below `./gradlew` commands should be run from the root of the project.
Note that all `./gradlew` commands should be run from the root of the project.

### Updating unit tests snapshots
### Updating Unit Test Snapshots

```sh
./gradlew updateSnapshots
```

### Updating proto files
### Updating Proto Files

```sh
./gradlew updateSnapshots
```

### Updating address books
### Updating Address Books

Update all address books:
To update all address books:

```sh
./gradlew examples:updateAddressbooks
```

Update address books only for a mainnet:
To update address books only for mainnet:

```sh
./gradlew examples:updateAddressbooksMainnet
```

Update address books only for a testnet:
To update address books only for testnet:

```sh
./gradlew examples:updateAddressbooksTestnet
```

Update address books only for a previewnet:
To update address books only for previewnet:

```sh
./gradlew examples:updateAddressbooksPreviewnet
```

[1] https://adoptium.net
174 changes: 74 additions & 100 deletions scripts/generate_contract_function_param_methods.py
Original file line number Diff line number Diff line change
@@ -1,87 +1,71 @@

#!/usr/bin/env python3

int_versions = []
uint_versions = []

int_array_versions = []
uint_array_versions = []

# does not generate 8 bit versions because those require some special treatment.

def add_with_param_type(bit_width, param_type, map_method_name, exception_comment = ""):
int_versions.append(
"/*\n"
"* Add a " + str(bit_width) + "-bit integer.\n"
"*\n"
"* @param value The integer to be added\n"
"* @return {@code this}\n"
"*/\n"
"public ContractFunctionParameters addInt" + str(bit_width) + "(" + param_type + " value) {\n"
" args.add(new Argument(\"int" + str(bit_width) + "\", int256(value, " + str(bit_width) + "), false));\n"
"\n"
" return this;\n"
"}\n"
)
uint_versions.append(
"/*\n"
"* Add a " + str(bit_width) + "-bit unsigned integer.\n"
"\n"
"* The value will be treated as unsigned during encoding (it will be zero-padded instead of\n"
"* sign-extended to 32 bytes).\n"
"*\n"
"* @param value The integer to be added\n"
"* @return {@code this}\n" +
exception_comment +
"*/\n"
"public ContractFunctionParameters addUint" + str(bit_width) + "(" + param_type + " value) {\n"
" args.add(new Argument(\"uint" + str(bit_width) + "\", uint256(value, " + str(bit_width) + "), false));\n"
"\n"
" return this;\n"
"}\n"
)
int_array_versions.append(
"/**\n"
"* Add a dynamic array of " + str(bit_width) + "-bit integers.\n"
"*\n"
"* @param intArray The array of integers to be added\n"
"* @return {@code this}\n"
"*/\n"
"public ContractFunctionParameters addInt" + str(bit_width) + "Array(" + param_type + "[] intArray) {\n"
" ByteString arrayBytes = ByteString.copyFrom(\n"
" J8Arrays.stream(intArray)." + map_method_name + "(i -> int256(i, " + str(bit_width) + "))\n"
" .collect(Collectors.toList()));\n"
"\n"
" arrayBytes = uint256(intArray.length, 32).concat(arrayBytes);\n"
"\n"
" args.add(new Argument(\"int" + str(bit_width) + "[]\", arrayBytes, true));\n"
"\n"
" return this;\n"
"}\n"
)
uint_array_versions.append(
"/**\n"
"* Add a dynamic array of " + str(bit_width) + "-bit unsigned integers.\n"
"\n"
"* The value will be treated as unsigned during encoding (it will be zero-padded instead of\n"
"* sign-extended to 32 bytes).\n"
"*\n"
"* @param intArray The array of integers to be added\n"
"* @return {@code this}\n" +
exception_comment +
"*/\n"
"public ContractFunctionParameters addUint" + str(bit_width) + "Array(" + param_type + "[] intArray) {\n"
" ByteString arrayBytes = ByteString.copyFrom(\n"
" J8Arrays.stream(intArray)." + map_method_name + "(i -> uint256(i, " + str(bit_width) + "))\n"
" .collect(Collectors.toList()));\n"
"\n"
" arrayBytes = uint256(intArray.length, 32).concat(arrayBytes);\n"
"\n"
" args.add(new Argument(\"uint" + str(bit_width) + "[]\", arrayBytes, true));\n"
"\n"
" return this;\n"
"}\n"
)

# Does not generate 8 bit versions because those require some special treatment.
def add_with_param_type(bit_width, param_type, map_method_name, exception_comment=""):
int_versions.append(f"""/**
* Add a {bit_width}-bit integer.
*
* @param value The integer to be added
* @return {{@code this}}
*/
public ContractFunctionParameters addInt{bit_width}({param_type} value) {{
args.add(new Argument(\"int{bit_width}\", int256(value, {bit_width}), false));
return this;
}}
""")
uint_versions.append(f"""/**
* Add a {bit_width}-bit unsigned integer.
*
* The value will be treated as unsigned during encoding (it will be zero-padded instead of
* sign-extended to 32 bytes).
*
* @param value The integer to be added
* @return {{@code this}}
{exception_comment}*/
public ContractFunctionParameters addUint{bit_width}({param_type} value) {{
args.add(new Argument(\"uint{bit_width}\", uint256(value, {bit_width}), false));
return this;
}}
""")
int_array_versions.append(f"""/**
* Add a dynamic array of {bit_width}-bit integers.
*
* @param intArray The array of integers to be added
* @return {{@code this}}
*/
public ContractFunctionParameters addInt{bit_width}Array({param_type}[] intArray) {{
ByteString arrayBytes = ByteString.copyFrom(
J8Arrays.stream(intArray).{map_method_name}(i -> int256(i, {bit_width}))
.collect(Collectors.toList()));
arrayBytes = uint256(intArray.length, 32).concat(arrayBytes);
args.add(new Argument(\"int{bit_width}[]\", arrayBytes, true));
return this;
}}
""")
uint_array_versions.append(f"""/**
* Add a dynamic array of {bit_width}-bit unsigned integers.
*
* The value will be treated as unsigned during encoding (it will be zero-padded instead of
* sign-extended to 32 bytes).
*
* @param intArray The array of integers to be added
* @return {{@code this}}
{exception_comment}*/
public ContractFunctionParameters addUint{bit_width}Array({param_type}[] intArray) {{
ByteString arrayBytes = ByteString.copyFrom(
J8Arrays.stream(intArray).{map_method_name}(i -> uint256(i, {bit_width}))
.collect(Collectors.toList()));
arrayBytes = uint256(intArray.length, 32).concat(arrayBytes);
args.add(new Argument(\"uint{bit_width}[]\", arrayBytes, true));
return this;
}}
""")

for bit_width in range(16, 257, 8):
if bit_width <= 32:
Expand All @@ -91,26 +75,16 @@ def add_with_param_type(bit_width, param_type, map_method_name, exception_commen
else:
add_with_param_type(bit_width, "BigInteger", "map", "* @throws IllegalArgumentException if {@code bigInt.signum() < 0}.\n")

f = open("output.txt", "w")

f.write("// XXXXXXXXXXXXXXXXXXXX INT VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")

for v in int_versions:
f.write(v + "\n");

f.write("// XXXXXXXXXXXXXXXXXXXX INT ARRAY VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")

for v in int_array_versions:
f.write(v + "\n");

f.write("// XXXXXXXXXXXXXXXXXXXX UINT VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")

for v in uint_versions:
f.write(v + "\n");

f.write("// XXXXXXXXXXXXXXXXXXXX UINT ARRAY VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")

for v in uint_array_versions:
f.write(v + "\n");

f.close()
with open("output.txt", "w") as f:
f.write("// XXXXXXXXXXXXXXXXXXXX INT VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")
for v in int_versions:
f.write(v + "\n")
f.write("// XXXXXXXXXXXXXXXXXXXX UINT VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")
for v in uint_versions:
f.write(v + "\n")
f.write("// XXXXXXXXXXXXXXXXXXXX INT ARRAY VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")
for v in int_array_versions:
f.write(v + "\n")
f.write("// XXXXXXXXXXXXXXXXXXXX UINT ARRAY VERSIONS XXXXXXXXXXXXXXXXXXXX\n\n")
for v in uint_array_versions:
f.write(v + "\n")
Loading