Skip to content

Commit

Permalink
tests, tests, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hendrikebbers committed Jul 16, 2024
1 parent b9400a5 commit 93ecba9
Show file tree
Hide file tree
Showing 12 changed files with 411 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.hedera.hashgraph.sdk.FileId;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.time.Instant;
import java.util.Objects;

/**
Expand All @@ -18,6 +19,8 @@ public interface FileClient {
@NonNull
FileId createFile(@NonNull byte[] contents) throws HederaException;

FileId createFile(@NonNull byte[] contents, @NonNull Instant expirationTime) throws HederaException;

/**
* Create a new file with the given contents.
* @param fileId the ID of the file to update
Expand Down Expand Up @@ -54,4 +57,14 @@ default void deleteFile(@NonNull String fileId) throws HederaException {
* @throws HederaException if the file could not be deleted
*/
void deleteFile(@NonNull FileId fileId) throws HederaException;

void updateFile(@NonNull FileId fileId, byte[] content) throws HederaException;

void updateExpirationTime(@NonNull FileId fileId, @NonNull Instant expirationTime) throws HederaException;

boolean isDeleted(@NonNull FileId fileId) throws HederaException;

int getSize(@NonNull FileId fileId) throws HederaException;

Instant getExpirationTime(@NonNull FileId fileId) throws HederaException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
import com.openelements.hedera.base.protocol.FileCreateRequest;
import com.openelements.hedera.base.protocol.FileCreateResult;
import com.openelements.hedera.base.protocol.FileDeleteRequest;
import com.openelements.hedera.base.protocol.FileInfoRequest;
import com.openelements.hedera.base.protocol.FileInfoResponse;
import com.openelements.hedera.base.protocol.FileUpdateRequest;
import com.openelements.hedera.base.protocol.FileUpdateResult;
import com.openelements.hedera.base.protocol.ProtocolLayerClient;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
import org.slf4j.Logger;
Expand All @@ -29,26 +35,46 @@ public FileClientImpl(@NonNull final ProtocolLayerClient protocolLayerClient) {

@Override
public FileId createFile(byte[] contents) throws HederaException {
return createFileImpl(contents, null);
}

@Override
public FileId createFile(@NonNull byte[] contents, @NonNull Instant expirationTime) throws HederaException {
return createFileImpl(contents, expirationTime);
}

private FileId createFileImpl(@NonNull byte[] contents, @Nullable Instant expirationTime) throws HederaException {
Objects.requireNonNull(contents, "fileId must not be null");
if(contents.length <= FileCreateRequest.FILE_CREATE_MAX_BYTES) {
final FileCreateRequest request = FileCreateRequest.of(contents);
if(contents.length > FileCreateRequest.FILE_MAX_SIZE) {
throw new HederaException("File contents must be less than " + FileCreateRequest.FILE_MAX_SIZE + " bytes");
}
if(expirationTime != null && expirationTime.isBefore(Instant.now())) {
throw new IllegalArgumentException("Expiration time must be in the future");
}
if(contents.length <= FileCreateRequest.FILE_CREATE_MAX_SIZE) {
final FileCreateRequest request;
if(expirationTime != null) {
request = FileCreateRequest.of(contents, expirationTime);
} else {
request = FileCreateRequest.of(contents);
}
final FileCreateResult result = protocolLayerClient.executeFileCreateTransaction(request);
return result.fileId();
} else {
if(log.isDebugEnabled()) {
final int appendCount = Math.floorDiv(contents.length, FileCreateRequest.FILE_CREATE_MAX_BYTES);
final int appendCount = Math.floorDiv(contents.length, FileCreateRequest.FILE_CREATE_MAX_SIZE);
log.debug("Content of size {} is to big for 1 FileCreate transaction. Will append {} FileAppend transactions", contents.length, appendCount);
}
byte[] start = Arrays.copyOf(contents, FileCreateRequest.FILE_CREATE_MAX_BYTES);
byte[] start = Arrays.copyOf(contents, FileCreateRequest.FILE_CREATE_MAX_SIZE);
final FileCreateRequest request = FileCreateRequest.of(start);
final FileCreateResult result = protocolLayerClient.executeFileCreateTransaction(request);
FileId fileId = result.fileId();
byte[] remaining = Arrays.copyOfRange(contents, FileCreateRequest.FILE_CREATE_MAX_BYTES, contents.length);
byte[] remaining = Arrays.copyOfRange(contents, FileCreateRequest.FILE_CREATE_MAX_SIZE, contents.length);
while(remaining.length > 0) {
final int length = Math.min(remaining.length, FileCreateRequest.FILE_CREATE_MAX_BYTES);
final int length = Math.min(remaining.length, FileCreateRequest.FILE_CREATE_MAX_SIZE);
byte[] next = Arrays.copyOf(remaining, length);
final FileAppendRequest appendRequest = FileAppendRequest.of(fileId, next);
final FileAppendResult appendResult = protocolLayerClient.executeFileAppendRequestTransaction(appendRequest);
protocolLayerClient.executeFileAppendRequestTransaction(appendRequest);
remaining = Arrays.copyOfRange(remaining, length, remaining.length);
}
return fileId;
Expand Down Expand Up @@ -78,4 +104,69 @@ public void deleteFile(@NonNull FileId fileId) throws HederaException {
throw new HederaException("Failed to delete file with fileId " + fileId, e);
}
}

@Override
public void updateFile(@NonNull FileId fileId, byte[] content) throws HederaException {
Objects.requireNonNull(fileId, "fileId must not be null");
Objects.requireNonNull(content, "content must not be null");
if(content.length > FileCreateRequest.FILE_MAX_SIZE) {
throw new HederaException("File contents must be less than " + FileCreateRequest.FILE_MAX_SIZE + " bytes");
}
if(content.length <= FileCreateRequest.FILE_CREATE_MAX_SIZE) {
final FileUpdateRequest request = FileUpdateRequest.of(fileId, content);
protocolLayerClient.executeFileUpdateRequestTransaction(request);
} else {
if(log.isDebugEnabled()) {
final int appendCount = Math.floorDiv(content.length, FileCreateRequest.FILE_CREATE_MAX_SIZE);
log.debug("Content of size {} is to big for 1 FileUpdate transaction. Will append {} FileAppend transactions", content.length, appendCount);
}
byte[] start = Arrays.copyOf(content, FileCreateRequest.FILE_CREATE_MAX_SIZE);
final FileUpdateRequest request = FileUpdateRequest.of(fileId, start);
protocolLayerClient.executeFileUpdateRequestTransaction(request);
byte[] remaining = Arrays.copyOfRange(content, FileCreateRequest.FILE_CREATE_MAX_SIZE, content.length);
while(remaining.length > 0) {
final int length = Math.min(remaining.length, FileCreateRequest.FILE_CREATE_MAX_SIZE);
byte[] next = Arrays.copyOf(remaining, length);
final FileAppendRequest appendRequest = FileAppendRequest.of(fileId, next);
protocolLayerClient.executeFileAppendRequestTransaction(appendRequest);
remaining = Arrays.copyOfRange(remaining, length, remaining.length);
}
}
}

@Override
public void updateExpirationTime(@NonNull FileId fileId, @NonNull Instant expirationTime) throws HederaException {
Objects.requireNonNull(fileId, "fileId must not be null");
Objects.requireNonNull(expirationTime, "expirationTime must not be null");

if(expirationTime.isBefore(Instant.now())) {
throw new IllegalArgumentException("Expiration time must be in the future");
}
final FileUpdateRequest request = FileUpdateRequest.of(fileId, expirationTime);
protocolLayerClient.executeFileUpdateRequestTransaction(request);
}

@Override
public boolean isDeleted(@NonNull FileId fileId) throws HederaException {
Objects.requireNonNull(fileId, "fileId must not be null");
final FileInfoRequest request = FileInfoRequest.of(fileId);
final FileInfoResponse infoResponse = protocolLayerClient.executeFileInfoQuery(request);
return infoResponse.deleted();
}

@Override
public int getSize(@NonNull FileId fileId) throws HederaException {
Objects.requireNonNull(fileId, "fileId must not be null");
final FileInfoRequest request = FileInfoRequest.of(fileId);
final FileInfoResponse infoResponse = protocolLayerClient.executeFileInfoQuery(request);
return infoResponse.size();
}

@Override
public Instant getExpirationTime(@NonNull FileId fileId) throws HederaException {
Objects.requireNonNull(fileId, "fileId must not be null");
final FileInfoRequest request = FileInfoRequest.of(fileId);
final FileInfoResponse infoResponse = protocolLayerClient.executeFileInfoQuery(request);
return infoResponse.expirationTime();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.hedera.hashgraph.sdk.FileContentsQuery;
import com.hedera.hashgraph.sdk.FileCreateTransaction;
import com.hedera.hashgraph.sdk.FileDeleteTransaction;
import com.hedera.hashgraph.sdk.FileInfo;
import com.hedera.hashgraph.sdk.FileInfoQuery;
import com.hedera.hashgraph.sdk.FileUpdateTransaction;
import com.hedera.hashgraph.sdk.Query;
import com.hedera.hashgraph.sdk.Transaction;
import com.hedera.hashgraph.sdk.TransactionReceipt;
Expand All @@ -32,6 +35,10 @@
import com.openelements.hedera.base.protocol.FileCreateResult;
import com.openelements.hedera.base.protocol.FileDeleteRequest;
import com.openelements.hedera.base.protocol.FileDeleteResult;
import com.openelements.hedera.base.protocol.FileInfoRequest;
import com.openelements.hedera.base.protocol.FileInfoResponse;
import com.openelements.hedera.base.protocol.FileUpdateRequest;
import com.openelements.hedera.base.protocol.FileUpdateResult;
import com.openelements.hedera.base.protocol.ProtocolLayerClient;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.List;
Expand Down Expand Up @@ -68,24 +75,69 @@ public FileContentsResponse executeFileContentsQuery(FileContentsRequest request
.setMaxQueryPayment(request.maxQueryPayment());
final ByteString byteString = executeQueryAndWait(query);
final byte[] bytes = byteString.toByteArray();
return new FileContentsResponse(bytes);
return new FileContentsResponse(request.fileId(), bytes);
}

public FileInfoResponse executeFileInfoQuery(FileInfoRequest request) throws HederaException {
final FileInfoQuery query = new FileInfoQuery().setFileId(request.fileId())
.setQueryPayment(request.queryPayment())
.setMaxQueryPayment(request.maxQueryPayment());
final FileInfo fileInfo = executeQueryAndWait(query);
if(fileInfo.size > Integer.MAX_VALUE) {
throw new HederaException("File size is too large to be represented as an integer");
}
return new FileInfoResponse(request.fileId(), (int) fileInfo.size, fileInfo.isDeleted, fileInfo.expirationTime);
}

@Override
public FileCreateResult executeFileCreateTransaction(FileCreateRequest request) throws HederaException {
Objects.requireNonNull(request, "request must not be null");
Objects.requireNonNull(request.contents(), "content must not be null");
if(request.contents().length > FileCreateRequest.FILE_CREATE_MAX_SIZE) {
throw new HederaException("File contents of 1 transaction must be less than " + FileCreateRequest.FILE_CREATE_MAX_SIZE + " bytes. Use FileAppend for larger files.");
}
final FileCreateTransaction transaction = new FileCreateTransaction()
.setContents(request.contents())
.setMaxTransactionFee(request.maxTransactionFee())
.setTransactionValidDuration(request.transactionValidDuration())
.setTransactionMemo(request.fileMemo())
.setKeys(Objects.requireNonNull(client.getOperatorPublicKey()));
if(request.expirationTime() != null) {
transaction.setExpirationTime(request.expirationTime());
}

final TransactionReceipt receipt = executeTransactionAndWaitOnReceipt(transaction);
return new FileCreateResult(receipt.transactionId, receipt.status, receipt.fileId);
}

@Override
public FileUpdateResult executeFileUpdateRequestTransaction(FileUpdateRequest request) throws HederaException {
Objects.requireNonNull(request, "request must not be null");
if(request.contents() != null && request.contents().length > FileCreateRequest.FILE_CREATE_MAX_SIZE) {
throw new HederaException("File contents of 1 transaction must be less than " + FileCreateRequest.FILE_CREATE_MAX_SIZE + " bytes. Use FileAppend for larger files.");
}
final FileUpdateTransaction transaction = new FileUpdateTransaction()
.setFileId(request.fileId())
.setMaxTransactionFee(request.maxTransactionFee())
.setTransactionValidDuration(request.transactionValidDuration())
.setTransactionMemo(request.fileMemo());
if(request.contents() != null) {
transaction.setContents(request.contents());
}
if(request.expirationTime() != null) {
transaction.setExpirationTime(request.expirationTime());
}
final TransactionReceipt receipt = executeTransactionAndWaitOnReceipt(transaction);
return new FileUpdateResult(receipt.transactionId, receipt.status);
}

@Override
public FileAppendResult executeFileAppendRequestTransaction(FileAppendRequest request) throws HederaException {
Objects.requireNonNull(request, "request must not be null");
Objects.requireNonNull(request.contents(), "content must not be null");
if(request.contents().length > FileCreateRequest.FILE_CREATE_MAX_SIZE) {
throw new HederaException("File contents of 1 transaction must be less than " + FileCreateRequest.FILE_CREATE_MAX_SIZE + " bytes. Use multiple FileAppend for larger files.");
}
final FileAppendTransaction transaction = new FileAppendTransaction()
.setFileId(request.fileId())
.setContents(request.contents())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.openelements.hedera.base.protocol;

public record FileContentsResponse(byte[] contents) {
import com.hedera.hashgraph.sdk.FileId;

public record FileContentsResponse(FileId fileId, byte[] contents) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,35 @@

import com.hedera.hashgraph.sdk.Hbar;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;

public record FileCreateRequest(Hbar maxTransactionFee,
Duration transactionValidDuration,
@NonNull byte[] contents,
@Nullable Instant expirationTime,
String fileMemo) implements TransactionRequest {

private static final String DEFAULT_FILE_MEMO = "";

public static final int FILE_CREATE_MAX_BYTES = 2048;
public static final int FILE_CREATE_MAX_SIZE = 2048;

public static final int FILE_MAX_SIZE = 1_024_000;

public FileCreateRequest {
Objects.requireNonNull(contents, "File contents are required");
if (contents.length > FILE_CREATE_MAX_BYTES) {
throw new IllegalArgumentException("File contents must be less than " + FILE_CREATE_MAX_BYTES + " bytes");
if (contents.length > FILE_CREATE_MAX_SIZE) {
throw new IllegalArgumentException("File contents must be less than " + FILE_CREATE_MAX_SIZE + " bytes");
}
}

public static FileCreateRequest of(@NonNull byte[] contents) {
return new FileCreateRequest(DEFAULT_MAX_TRANSACTION_FEE, DEFAULT_TRANSACTION_VALID_DURATION, contents, DEFAULT_FILE_MEMO);
return new FileCreateRequest(DEFAULT_MAX_TRANSACTION_FEE, DEFAULT_TRANSACTION_VALID_DURATION, contents, null, DEFAULT_FILE_MEMO);
}

public static FileCreateRequest of(@NonNull byte[] contents, @NonNull Instant expirationTime) {
return new FileCreateRequest(DEFAULT_MAX_TRANSACTION_FEE, DEFAULT_TRANSACTION_VALID_DURATION, contents, expirationTime, DEFAULT_FILE_MEMO);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.openelements.hedera.base.protocol;

import com.hedera.hashgraph.sdk.FileId;
import com.hedera.hashgraph.sdk.Hbar;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Objects;

public record FileInfoRequest(@NonNull FileId fileId, @Nullable Hbar queryPayment, @Nullable Hbar maxQueryPayment) implements QueryRequest {

public FileInfoRequest {
Objects.requireNonNull(fileId, "fileId must not be null");
}

@NonNull
public static FileInfoRequest of(@NonNull String fileId) {
Objects.requireNonNull(fileId, "fileId must not be null");
return of(FileId.fromString(fileId));
}

@NonNull
public static FileInfoRequest of(@NonNull FileId fileId) {
return new FileInfoRequest(fileId, null, null);
}

@Override
public Hbar queryPayment() {
return queryPayment;
}

@Override
public Hbar maxQueryPayment() {
return maxQueryPayment;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.openelements.hedera.base.protocol;

import com.hedera.hashgraph.sdk.FileId;
import java.time.Instant;

public record FileInfoResponse(FileId fileId, int size, boolean deleted, Instant expirationTime){
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.openelements.hedera.base.protocol;

import com.hedera.hashgraph.sdk.FileId;
import com.hedera.hashgraph.sdk.Hbar;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;

public record FileUpdateRequest(Hbar maxTransactionFee,

Duration transactionValidDuration,

FileId fileId,

@Nullable byte[] contents,

@Nullable Instant expirationTime,
String fileMemo) implements TransactionRequest {

private static final String DEFAULT_FILE_MEMO = "";

public static final int FILE_CREATE_MAX_BYTES = 2048;

public FileUpdateRequest {
if (contents != null && contents.length > FILE_CREATE_MAX_BYTES) {
throw new IllegalArgumentException("File contents must be less than " + FILE_CREATE_MAX_BYTES + " bytes");
}
}

public static FileUpdateRequest of(@NonNull FileId fileId, @NonNull byte[] contents) {
return new FileUpdateRequest(DEFAULT_MAX_TRANSACTION_FEE, DEFAULT_TRANSACTION_VALID_DURATION, fileId, contents, null, DEFAULT_FILE_MEMO);
}

public static FileUpdateRequest of(@NonNull FileId fileId, @NonNull Instant expirationTime) {
return new FileUpdateRequest(DEFAULT_MAX_TRANSACTION_FEE, DEFAULT_TRANSACTION_VALID_DURATION, fileId, null, expirationTime, DEFAULT_FILE_MEMO);
}
}
Loading

0 comments on commit 93ecba9

Please sign in to comment.