BlockchainBaseTemplate.java
/*
* @copyright defined in LICENSE.txt
*/
package hera.client.internal;
import static hera.util.TransportUtils.copyFrom;
import static org.slf4j.LoggerFactory.getLogger;
import static types.AergoRPCServiceGrpc.newFutureStub;
import com.google.protobuf.ByteString;
import hera.ContextProvider;
import hera.ContextProviderInjectable;
import hera.annotation.ApiAudience;
import hera.annotation.ApiStability;
import hera.api.function.Function0;
import hera.api.function.Function1;
import hera.api.function.Function2;
import hera.api.model.AccountAddress;
import hera.api.model.AccountTotalVote;
import hera.api.model.BlockchainStatus;
import hera.api.model.ChainInfo;
import hera.api.model.ChainStats;
import hera.api.model.ElectedCandidate;
import hera.api.model.NodeStatus;
import hera.api.model.Peer;
import hera.api.model.PeerMetric;
import hera.api.model.ServerInfo;
import hera.client.ChannelInjectable;
import hera.transport.AccountAddressConverterFactory;
import hera.transport.AccountTotalVoteConverterFactory;
import hera.transport.BlockchainStatusConverterFactory;
import hera.transport.ChainInfoConverterFactory;
import hera.transport.ChainStatsConverterFactory;
import hera.transport.ElectedCandidateConverterFactory;
import hera.transport.ModelConverter;
import hera.transport.NodeStatusConverterFactory;
import hera.transport.PeerConverterFactory;
import hera.transport.PeerMetricConverterFactory;
import hera.transport.ServerInfoConverterFactory;
import io.grpc.ManagedChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import lombok.Getter;
import org.slf4j.Logger;
import types.AergoRPCServiceGrpc.AergoRPCServiceFutureStub;
import types.Metric;
import types.Rpc;
@ApiAudience.Private
@ApiStability.Unstable
public class BlockchainBaseTemplate implements ChannelInjectable, ContextProviderInjectable {
protected static final long NODE_STATUS_TIMEOUT = 3000L;
protected final transient Logger logger = getLogger(getClass());
protected final ModelConverter<BlockchainStatus, Rpc.BlockchainStatus> blockchainConverter =
new BlockchainStatusConverterFactory().create();
protected final ModelConverter<ChainInfo, Rpc.ChainInfo> chainInfoConverter =
new ChainInfoConverterFactory().create();
protected final ModelConverter<ChainStats, Rpc.ChainStats> chainStatsConverter =
new ChainStatsConverterFactory().create();
protected final ModelConverter<Peer, Rpc.Peer> peerConverter =
new PeerConverterFactory().create();
protected final ModelConverter<PeerMetric, Metric.PeerMetric> peerMetricConverter =
new PeerMetricConverterFactory().create();
protected final ModelConverter<ServerInfo, Rpc.ServerInfo> serverInfoConverter =
new ServerInfoConverterFactory().create();
protected final ModelConverter<NodeStatus, Rpc.SingleBytes> nodeStatusConverter =
new NodeStatusConverterFactory().create();
protected final ModelConverter<AccountAddress, ByteString> accountAddressConverter =
new AccountAddressConverterFactory().create();
protected final ModelConverter<ElectedCandidate, Rpc.Vote> electedCandidateConverter =
new ElectedCandidateConverterFactory().create();
protected final ModelConverter<AccountTotalVote, Rpc.AccountVoteInfo> accountTotalVoteConverter =
new AccountTotalVoteConverterFactory().create();
protected AccountBaseTemplate accountBaseTemplate = new AccountBaseTemplate();
protected TransactionBaseTemplate transactionBaseTemplate = new TransactionBaseTemplate();
@Getter
protected AergoRPCServiceFutureStub aergoService;
protected ContextProvider contextProvider;
@Override
public void setChannel(final ManagedChannel channel) {
this.aergoService = newFutureStub(channel);
this.accountBaseTemplate.setChannel(channel);
this.transactionBaseTemplate.setChannel(channel);
}
@Override
public void setContextProvider(final ContextProvider contextProvider) {
this.contextProvider = contextProvider;
this.accountBaseTemplate.setContextProvider(contextProvider);
this.transactionBaseTemplate.setContextProvider(contextProvider);
}
@Getter
private final Function0<Future<BlockchainStatus>> blockchainStatusFunction =
new Function0<Future<BlockchainStatus>>() {
@Override
public Future<BlockchainStatus> apply() {
logger.debug("Get blockchain status");
final Rpc.Empty empty = Rpc.Empty.newBuilder().build();
logger.trace("AergoService blockchain arg: {}", empty);
final Future<Rpc.BlockchainStatus> rawFuture = aergoService.blockchain(empty);
final Future<BlockchainStatus> convertedFuture = HerajFutures.transform(rawFuture,
new Function1<Rpc.BlockchainStatus, BlockchainStatus>() {
@Override
public BlockchainStatus apply(final Rpc.BlockchainStatus rpcBlockchainStatus) {
return blockchainConverter.convertToDomainModel(rpcBlockchainStatus);
}
});
return convertedFuture;
}
};
@Getter
private final Function0<Future<ChainInfo>> chainInfoFunction =
new Function0<Future<ChainInfo>>() {
@Override
public Future<ChainInfo> apply() {
logger.debug("Get chain info");
final Rpc.Empty empty = Rpc.Empty.newBuilder().build();
logger.trace("AergoService getChainInfo arg: {}", empty);
final Future<Rpc.ChainInfo> rawFuture = aergoService.getChainInfo(empty);
final Future<ChainInfo> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Rpc.ChainInfo, ChainInfo>() {
@Override
public ChainInfo apply(final Rpc.ChainInfo rpcChainInfo) {
return chainInfoConverter.convertToDomainModel(rpcChainInfo);
}
});
return convertedFuture;
}
};
@Getter
private final Function0<Future<ChainStats>> chainStatsFunction =
new Function0<Future<ChainStats>>() {
@Override
public Future<ChainStats> apply() {
logger.debug("Get chain info");
final Rpc.Empty empty = Rpc.Empty.newBuilder().build();
logger.trace("AergoService getChainStats arg: {}", empty);
final Future<Rpc.ChainStats> rawFuture = aergoService.chainStat(empty);
final Future<ChainStats> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Rpc.ChainStats, ChainStats>() {
@Override
public ChainStats apply(final Rpc.ChainStats rpcChainStatus) {
return chainStatsConverter.convertToDomainModel(rpcChainStatus);
}
});
return convertedFuture;
}
};
@Getter
private final Function2<Boolean, Boolean, Future<List<Peer>>> listPeersFunction =
new Function2<Boolean, Boolean, Future<List<Peer>>>() {
@Override
public Future<List<Peer>> apply(final Boolean showHidden,
final Boolean showSelf) {
logger.debug("List peers with showHidden: {}, showSelf: {}", showHidden, showSelf);
final Rpc.PeersParams peersParams = Rpc.PeersParams.newBuilder()
.setNoHidden(!showHidden.booleanValue())
.setShowSelf(showSelf.booleanValue())
.build();
logger.trace("AergoService getPeers arg: {}", peersParams);
final Future<Rpc.PeerList> rawFuture = aergoService.getPeers(peersParams);
final Future<List<Peer>> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Rpc.PeerList, List<Peer>>() {
@Override
public List<Peer> apply(final Rpc.PeerList rpcPeerList) {
final List<Peer> domainPeers = new ArrayList<>();
for (final Rpc.Peer rpcPeer : rpcPeerList.getPeersList()) {
domainPeers.add(peerConverter.convertToDomainModel(rpcPeer));
}
return domainPeers;
}
});
return convertedFuture;
}
};
@Getter
private final Function0<Future<List<PeerMetric>>> listPeersMetricsFunction =
new Function0<Future<List<PeerMetric>>>() {
@Override
public Future<List<PeerMetric>> apply() {
logger.debug("List peer metrics");
final Metric.MetricsRequest rpcMetricRequest = Metric.MetricsRequest.newBuilder()
.addTypes(Metric.MetricType.P2P_NETWORK)
.build();
logger.trace("AergoService metric arg: {}", rpcMetricRequest);
final Future<Metric.Metrics> rawFuture = aergoService.metric(rpcMetricRequest);
final Future<List<PeerMetric>> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Metric.Metrics, List<PeerMetric>>() {
@Override
public List<PeerMetric> apply(final Metric.Metrics rpcPeerMetrics) {
final List<PeerMetric> domainPeerMetrics = new ArrayList<>();
for (final Metric.PeerMetric rpcPeerMetric : rpcPeerMetrics.getPeersList()) {
domainPeerMetrics.add(peerMetricConverter.convertToDomainModel(rpcPeerMetric));
}
return domainPeerMetrics;
}
});
return convertedFuture;
}
};
@Getter
private final Function1<List<String>, Future<ServerInfo>> serverInfoFunction =
new Function1<List<String>, Future<ServerInfo>>() {
@Override
public Future<ServerInfo> apply(final List<String> keys) {
logger.debug("Get node status");
final Rpc.KeyParams rpcServerInfoRequest = Rpc.KeyParams.newBuilder()
.addAllKey(keys)
.build();
logger.trace("AergoService getServerInfo arg: {}", rpcServerInfoRequest);
final Future<Rpc.ServerInfo> rawFuture =
aergoService.getServerInfo(rpcServerInfoRequest);
final Future<ServerInfo> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Rpc.ServerInfo, ServerInfo>() {
@Override
public ServerInfo apply(final Rpc.ServerInfo rpcServerInfo) {
return serverInfoConverter.convertToDomainModel(rpcServerInfo);
}
});
return convertedFuture;
}
};
@Getter
private final Function0<Future<NodeStatus>> nodeStatusFunction =
new Function0<Future<NodeStatus>>() {
@Override
public Future<NodeStatus> apply() {
logger.debug("Get node status");
final Rpc.NodeReq rpcNodeRequest = Rpc.NodeReq.newBuilder()
.setTimeout(copyFrom(NODE_STATUS_TIMEOUT))
.build();
logger.trace("AergoService nodeState arg: {}", rpcNodeRequest);
final Future<Rpc.SingleBytes> rawFuture = aergoService.nodeState(rpcNodeRequest);
final Future<NodeStatus> convertedFuture =
HerajFutures.transform(rawFuture, new Function1<Rpc.SingleBytes, NodeStatus>() {
@Override
public NodeStatus apply(final Rpc.SingleBytes rpcNodeStatus) {
return nodeStatusConverter.convertToDomainModel(rpcNodeStatus);
}
});
return convertedFuture;
}
};
}