Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #411 tier ref script fee implementation for Conway era #414

Merged
merged 5 commits into from
Aug 19, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.bloxbean.cardano.client.backend.api;

import com.bloxbean.cardano.client.api.ScriptSupplier;
import com.bloxbean.cardano.client.api.exception.ApiException;
import com.bloxbean.cardano.client.api.exception.ApiRuntimeException;
import com.bloxbean.cardano.client.plutus.spec.PlutusScript;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;

public class DefaultScriptSupplier implements ScriptSupplier {
private final static Logger log = LoggerFactory.getLogger(DefaultScriptSupplier.class);

private ScriptService scriptService;

public DefaultScriptSupplier(ScriptService scriptService) {
this.scriptService = scriptService;
}

@Override
public Optional<PlutusScript> getScript(String scriptHash) {
try {
var result = scriptService.getPlutusScript(scriptHash);
if (result.isSuccessful())
return Optional.of(result.getValue());
else {
log.debug("Error fetching script for hash: {}, {}", scriptHash, result.getResponse());
return Optional.empty();
}
} catch (ApiException e) {
log.debug("Error fetching script for hash: {}", scriptHash, e);
throw new ApiRuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bloxbean.cardano.client.util;

/**
* A functional interface that represents a function which may throw a checked exception.
* This is useful in scenarios where you want to use lambda expressions or method references
* that throw checked exceptions, particularly in stream operations or other functional contexts.
*
* @param <T> The type of the input to the function.
*/
@FunctionalInterface
public interface CheckedFunction<T> {
T apply() throws Exception;
}
70 changes: 70 additions & 0 deletions common/src/main/java/com/bloxbean/cardano/client/util/Try.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.bloxbean.cardano.client.util;

/**
* A utility class that encapsulates a computation that may either result in a successful value
* or throw an exception. This class provides a way to handle checked exceptions in a functional
* style, allowing the use of such methods in stream operations without needing to use try-catch blocks.
*
* @param <T> The type of the result of the computation.
*/
public class Try<T> {
private final T result;
private final Exception exception;

/**
* Private constructor to initialize a Try instance.
*
* @param result The result of the computation, or null if an exception occurred.
* @param exception The exception thrown by the computation, or null if the computation was successful.
*/
private Try(T result, Exception exception) {
this.result = result;
this.exception = exception;
}

/**
* Executes the provided CheckedFunction, capturing any thrown exceptions.
*
* @param supplier A function that produces a result, potentially throwing an exception.
* @param <T> The type of the result produced by the function.
* @return A Try instance representing either a successful result or a captured exception.
*/
public static <T> Try<T> of(CheckedFunction<T> supplier) {
try {
return new Try<>(supplier.apply(), null);
} catch (Exception e) {
return new Try<>(null, e);
}
}

/**
* Checks whether the computation was successful.
*
* @return true if the computation was successful (i.e., no exception was thrown), false otherwise.
*/
public boolean isSuccess() {
return exception == null;
}

/**
* Returns the result of the computation, if it was successful.
*
* @return The result of the computation.
* @throws RuntimeException if the computation resulted in an exception.
*/
public T get() {
if (exception != null) {
throw new RuntimeException(exception);
}
return result;
}

/**
* Returns the exception that was thrown during the computation, if any.
*
* @return The exception thrown by the computation, or null if the computation was successful.
*/
public Exception getException() {
return exception;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import com.bloxbean.cardano.client.plutus.spec.PlutusScript;

import java.util.Optional;

/**
* Implement this interface to provide PlutusScript
*/
@FunctionalInterface
public interface ScriptSupplier {
PlutusScript getScript(String scriptHash);
Optional<PlutusScript> getScript(String scriptHash);
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ public class ProtocolParams {
private BigInteger govActionDeposit;
private BigInteger drepDeposit;
private Integer drepActivity;
private Integer minFeeRefScriptCostPerByte;
private BigDecimal minFeeRefScriptCostPerByte;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.bloxbean.cardano.client.api.model;

import java.util.Optional;

/**
* A generic wrapper class that encapsulates the result of an operation, which can either be a successful value or an error.
*
* <p>This class provides a way to handle operations that might return a result or throw an exception, without
* immediately throwing the exception. Instead, the result or error is stored in the `ResultWrapper`, allowing
* the caller to decide how to handle the success or failure.</p>
*
* @param <T> The type of the result value.
*/
public class ResultWrapper<T> {
private final Optional<T> value;
private final Exception error;

/**
* Private constructor to create a ResultWrapper instance.
*
* @param value the value of the result, wrapped in an Optional.
* @param error the exception that occurred, if any.
*/
private ResultWrapper(Optional<T> value, Exception error) {
this.value = value;
this.error = error;
}

/**
* Creates a ResultWrapper representing a successful result.
*
* @param value the result value.
* @param <T> the type of the result.
* @return a ResultWrapper containing the result value.
*/
public static <T> ResultWrapper<T> success(T value) {
return new ResultWrapper<>(Optional.ofNullable(value), null);
}

/**
* Creates a ResultWrapper representing a failure due to an exception.
*
* @param error the exception that occurred.
* @param <T> the type of the result that would have been returned on success.
* @return a ResultWrapper containing the exception.
*/
public static <T> ResultWrapper<T> failure(Exception error) {
return new ResultWrapper<>(Optional.empty(), error);
}

/**
* Returns the result value, if present.
*
* @return an Optional containing the result value, or an empty Optional if the operation failed.
*/
public Optional<T> getValue() {
return value;
}

/**
* Returns the exception that occurred, if any.
*
* @return an Optional containing the exception, or an empty Optional if the operation was successful.
*/
public Optional<Exception> getError() {
return Optional.ofNullable(error);
}

/**
* Checks if the operation was successful.
*
* @return true if the result is present (indicating success), false otherwise.
*/
public boolean isSuccess() {
return value.isPresent();
}

/**
* Checks if the operation resulted in a failure.
*
* @return true if an error occurred, false otherwise.
*/
public boolean isFailure() {
return error != null;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bloxbean.cardano.client.api.util;

import com.bloxbean.cardano.client.api.ScriptSupplier;
import com.bloxbean.cardano.client.api.UtxoSupplier;
import com.bloxbean.cardano.client.util.Try;
import com.bloxbean.cardano.client.transaction.spec.Transaction;

import java.util.Optional;

public class ReferenceScriptUtil {

/**
* Fetches the reference scripts from the utxo supplier and calculates the size of the reference scripts
*
* @param utxoSupplier utxo supplier
* @param scriptSupplier script supplier
* @param transaction transaction
* @return size of the reference scripts
*/
public static long fetchAndCalculateReferenceScriptsSize(UtxoSupplier utxoSupplier, ScriptSupplier scriptSupplier, Transaction transaction) {
return transaction.getBody().getReferenceInputs()
.stream()
.flatMap(refInput -> utxoSupplier.getTxOutput(refInput.getTransactionId(), refInput.getIndex()).stream()
.map(utxo -> scriptSupplier.getScript(utxo.getReferenceScriptHash()))
.flatMap(Optional::stream))
.map(script -> Try.of(() -> script.scriptRefBytes().length))
.filter(Try::isSuccess)
.mapToLong(Try::get)
.sum();

}

}
Loading
Loading