ContractTemplate.java
/*
* @copyright defined in LICENSE.txt
*/
package hera.client;
import static hera.api.function.Functions.identify;
import static hera.client.ClientConstants.CONTRACT_DEPLOY;
import static hera.client.ClientConstants.CONTRACT_EXECUTE;
import static hera.client.ClientConstants.CONTRACT_GETINTERFACE;
import static hera.client.ClientConstants.CONTRACT_GETRECEIPT;
import static hera.client.ClientConstants.CONTRACT_LIST_EVENT;
import static hera.client.ClientConstants.CONTRACT_QUERY;
import static hera.client.ClientConstants.CONTRACT_REDEPLOY;
import static hera.client.ClientConstants.CONTRACT_SUBSCRIBE_EVENT;
import hera.ContextProvider;
import hera.ContextProviderInjectable;
import hera.annotation.ApiAudience;
import hera.annotation.ApiStability;
import hera.api.ContractOperation;
import hera.api.function.Function1;
import hera.api.function.Function2;
import hera.api.function.Function4;
import hera.api.function.Function5;
import hera.api.model.Account;
import hera.api.model.ContractAddress;
import hera.api.model.ContractDefinition;
import hera.api.model.ContractInterface;
import hera.api.model.ContractInvocation;
import hera.api.model.ContractResult;
import hera.api.model.ContractTxHash;
import hera.api.model.ContractTxReceipt;
import hera.api.model.Event;
import hera.api.model.EventFilter;
import hera.api.model.Fee;
import hera.api.model.StreamObserver;
import hera.api.model.Subscription;
import hera.client.internal.ContractBaseTemplate;
import hera.exception.RpcException;
import hera.exception.RpcExceptionConverter;
import hera.key.Signer;
import hera.strategy.PriorityProvider;
import hera.strategy.StrategyApplier;
import hera.util.ExceptionConverter;
import io.grpc.ManagedChannel;
import java.util.List;
import java.util.concurrent.Future;
import lombok.AccessLevel;
import lombok.Getter;
@ApiAudience.Private
@ApiStability.Unstable
public class ContractTemplate
implements ContractOperation, ChannelInjectable, ContextProviderInjectable {
protected final ExceptionConverter<RpcException> exceptionConverter = new RpcExceptionConverter();
protected ContractBaseTemplate contractBaseTemplate = new ContractBaseTemplate();
protected ContextProvider contextProvider;
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final StrategyApplier strategyApplier =
StrategyApplier.of(contextProvider.get(), PriorityProvider.get());
@Override
public void setChannel(final ManagedChannel channel) {
this.contractBaseTemplate.setChannel(channel);
}
@Override
public void setContextProvider(final ContextProvider contextProvider) {
this.contextProvider = contextProvider;
this.contractBaseTemplate.setContextProvider(contextProvider);
}
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function1<ContractTxHash,
Future<ContractTxReceipt>> receiptFunction = getStrategyApplier().apply(
identify(contractBaseTemplate.getReceiptFunction(), CONTRACT_GETRECEIPT));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function4<Signer, ContractDefinition, Long, Fee,
Future<ContractTxHash>> deployFunction =
getStrategyApplier()
.apply(identify(contractBaseTemplate.getDeployFunction(), CONTRACT_DEPLOY));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function5<Signer, ContractAddress, ContractDefinition, Long, Fee,
Future<ContractTxHash>> reDeployFunction =
getStrategyApplier()
.apply(identify(contractBaseTemplate.getReDeployFunction(), CONTRACT_REDEPLOY));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function1<ContractAddress,
Future<ContractInterface>> contractInterfaceFunction =
getStrategyApplier().apply(identify(contractBaseTemplate.getContractInterfaceFunction(),
CONTRACT_GETINTERFACE));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function4<Signer, ContractInvocation, Long, Fee,
Future<ContractTxHash>> executeFunction =
getStrategyApplier()
.apply(identify(contractBaseTemplate.getExecuteFunction(), CONTRACT_EXECUTE));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function1<ContractInvocation, Future<ContractResult>> queryFunction =
getStrategyApplier().apply(identify(contractBaseTemplate.getQueryFunction(), CONTRACT_QUERY));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function1<EventFilter, Future<List<Event>>> listEventFunction =
getStrategyApplier()
.apply(identify(contractBaseTemplate.getListEventFunction(), CONTRACT_LIST_EVENT));
@Getter(lazy = true, value = AccessLevel.PROTECTED)
private final Function2<EventFilter, StreamObserver<Event>,
Future<Subscription<Event>>> subscribeEventFunction =
getStrategyApplier().apply(
identify(contractBaseTemplate.getSubscribeEventFunction(), CONTRACT_SUBSCRIBE_EVENT));
@Override
public ContractTxReceipt getReceipt(final ContractTxHash contractTxHash) {
try {
return getReceiptFunction().apply(contractTxHash).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public ContractTxHash deploy(final Account creator, final ContractDefinition contractDefinition,
final long nonce) {
return deploy(creator, contractDefinition, nonce, Fee.ZERO);
}
@Override
public ContractTxHash deploy(final Account creator, final ContractDefinition contractDefinition,
final long nonce, final Fee fee) {
if (null == creator.getKey()) {
throw new UnsupportedOperationException();
}
return deploy(creator.getKey(), contractDefinition, nonce, fee);
}
@Override
public ContractTxHash deploy(final Signer signer, final ContractDefinition contractDefinition,
final long nonce, final Fee fee) {
try {
return getDeployFunction().apply(signer, contractDefinition, nonce, fee).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public ContractTxHash redeploy(final Signer signer, final ContractAddress existingContract,
final ContractDefinition contractDefinition, final long nonce, final Fee fee) {
try {
return getReDeployFunction().apply(signer, existingContract, contractDefinition, nonce, fee)
.get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public ContractInterface getContractInterface(final ContractAddress contractAddress) {
try {
return getContractInterfaceFunction().apply(contractAddress).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public ContractTxHash execute(final Account executor, final ContractInvocation contractInvocation,
final long nonce) {
return execute(executor, contractInvocation, nonce, Fee.ZERO);
}
@Override
public ContractTxHash execute(final Account executor, final ContractInvocation contractInvocation,
final long nonce, final Fee fee) {
if (null == executor.getKey()) {
throw new UnsupportedOperationException();
}
return execute(executor.getKey(), contractInvocation, nonce, fee);
}
@Override
public ContractTxHash execute(final Signer signer, final ContractInvocation contractInvocation,
final long nonce, final Fee fee) {
try {
return getExecuteFunction().apply(signer, contractInvocation, nonce, fee).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public ContractResult query(final ContractInvocation contractInvocation) {
try {
return getQueryFunction().apply(contractInvocation).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public List<Event> listEvents(final EventFilter filter) {
try {
return getListEventFunction().apply(filter).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
@Override
public Subscription<Event> subscribeEvent(final EventFilter filter,
final StreamObserver<Event> observer) {
try {
return getSubscribeEventFunction().apply(filter, observer).get();
} catch (Exception e) {
throw exceptionConverter.convert(e);
}
}
}