AccountBaseTemplate.java
- /*
- * @copyright defined in LICENSE.txt
- */
- package hera.client.internal;
- import static hera.util.ValidationUtils.assertTrue;
- 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.Function1;
- import hera.api.function.Function2;
- import hera.api.function.Function3;
- import hera.api.function.Function4;
- import hera.api.model.Account;
- import hera.api.model.AccountAddress;
- import hera.api.model.AccountState;
- import hera.api.model.AccountTotalVote;
- import hera.api.model.Aer;
- import hera.api.model.BytesValue;
- import hera.api.model.ElectedCandidate;
- import hera.api.model.RawTransaction;
- import hera.api.model.StakeInfo;
- import hera.api.model.Transaction;
- import hera.api.model.TxHash;
- import hera.client.ChannelInjectable;
- import hera.exception.TransactionVerificationException;
- import hera.key.Signer;
- import hera.key.TxSigner;
- import hera.transport.AccountAddressConverterFactory;
- import hera.transport.AccountStateConverterFactory;
- import hera.transport.AccountTotalVoteConverterFactory;
- import hera.transport.ElectedCandidateConverterFactory;
- import hera.transport.ModelConverter;
- import hera.transport.StakeInfoConverterFactory;
- import hera.transport.TransactionConverterFactory;
- 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.Blockchain;
- import types.Rpc;
- @ApiAudience.Private
- @ApiStability.Unstable
- public class AccountBaseTemplate implements ChannelInjectable, ContextProviderInjectable {
- protected final transient Logger logger = getLogger(getClass());
- protected final ModelConverter<AccountAddress, ByteString> accountAddressConverter =
- new AccountAddressConverterFactory().create();
- protected final ModelConverter<AccountState, Blockchain.State> accountStateConverter =
- new AccountStateConverterFactory().create();
- protected final ModelConverter<StakeInfo, Rpc.Staking> stakingInfoConverter =
- new StakeInfoConverterFactory().create();
- protected final ModelConverter<Transaction, Blockchain.Tx> transactionConverter =
- new TransactionConverterFactory().create();
- protected final ModelConverter<ElectedCandidate, Rpc.Vote> electedCandidateConverter =
- new ElectedCandidateConverterFactory().create();
- protected final ModelConverter<AccountTotalVote, Rpc.AccountVoteInfo> accountTotalVoteConverter =
- new AccountTotalVoteConverterFactory().create();
- @Getter
- protected AergoRPCServiceFutureStub aergoService;
- protected ContextProvider contextProvider;
- protected TransactionBaseTemplate transactionBaseTemplate = new TransactionBaseTemplate();
- @Override
- public void setContextProvider(final ContextProvider contextProvider) {
- this.contextProvider = contextProvider;
- this.transactionBaseTemplate.setContextProvider(contextProvider);
- }
- @Override
- public void setChannel(final ManagedChannel channel) {
- this.aergoService = newFutureStub(channel);
- this.transactionBaseTemplate.setChannel(channel);
- }
- @Getter
- private final Function1<AccountAddress, Future<AccountState>> stateFunction =
- new Function1<AccountAddress, Future<AccountState>>() {
- @Override
- public Future<AccountState> apply(final AccountAddress address) {
- logger.debug("GetState with {}", address);
- final Rpc.SingleBytes rpcAddress = Rpc.SingleBytes.newBuilder()
- .setValue(accountAddressConverter.convertToRpcModel(address))
- .build();
- logger.trace("AergoService getstate arg: {}", rpcAddress);
- final Future<Blockchain.State> rawFuture = aergoService.getState(rpcAddress);
- final Future<AccountState> convertedFuture =
- HerajFutures.transform(rawFuture, new Function1<Blockchain.State, AccountState>() {
- @Override
- public AccountState apply(final Blockchain.State state) {
- final AccountState withoutAddress =
- accountStateConverter.convertToDomainModel(state);
- return AccountState.newBuilder().address(address)
- .nonce(withoutAddress.getNonce())
- .balance(withoutAddress.getBalance())
- .build();
- }
- });
- return convertedFuture;
- }
- };
- @Getter
- private final Function3<Signer, String, Long, Future<TxHash>> createNameFunction =
- new Function3<Signer, String, Long, Future<TxHash>>() {
- @Override
- public Future<TxHash> apply(final Signer signer, final String name,
- final Long nonce) {
- logger.debug("Create account name with signer: {}, name: {}, nonce: {}",
- signer.getPrincipal(), name, nonce);
- final RawTransaction rawTransaction = RawTransaction.newCreateNameTxBuilder()
- .chainIdHash(contextProvider.get().getChainIdHash())
- .from(signer.getPrincipal())
- .nonce(nonce)
- .name(name)
- .build();
- final Transaction signed = signer.sign(rawTransaction);
- return transactionBaseTemplate.getCommitFunction().apply(signed);
- }
- };
- @Getter
- private final Function4<Signer, String, AccountAddress, Long,
- Future<TxHash>> updateNameFunction = new Function4<Signer, String,
- AccountAddress, Long, Future<TxHash>>() {
- @Override
- public Future<TxHash> apply(final Signer signer, final String name,
- final AccountAddress newOwner, final Long nonce) {
- logger.debug("Update account name with signer: {}, name: {}, to account: {}, nonce: {}",
- signer, name, newOwner, nonce);
- final RawTransaction rawTransaction = RawTransaction.newUpdateNameTxBuilder()
- .chainIdHash(contextProvider.get().getChainIdHash())
- .from(signer.getPrincipal())
- .nonce(nonce)
- .name(name)
- .newOwner(newOwner)
- .build();
- final Transaction signed = signer.sign(rawTransaction);
- return transactionBaseTemplate.getCommitFunction().apply(signed);
- }
- };
- @Getter
- private final Function2<String, Long, Future<AccountAddress>> getNameOwnerFunction =
- new Function2<String, Long, Future<AccountAddress>>() {
- @Override
- public Future<AccountAddress> apply(final String name, final Long blockNumber) {
- logger.debug("Get name owner of name: {}, blockNumber: {}", name, blockNumber);
- assertTrue(blockNumber >= 0, "Block number must >= 0");
- final Rpc.Name rpcName = Rpc.Name.newBuilder()
- .setName(name)
- .setBlockNo(blockNumber)
- .build();
- logger.trace("AergoService getNameInfo arg: {}", rpcName);
- final Future<Rpc.NameInfo> rawFuture = aergoService.getNameInfo(rpcName);
- final Future<AccountAddress> convertedFuture =
- HerajFutures.transform(rawFuture, new Function1<Rpc.NameInfo, AccountAddress>() {
- @Override
- public AccountAddress apply(final Rpc.NameInfo nameInfo) {
- final AccountAddress converted =
- accountAddressConverter.convertToDomainModel(nameInfo.getOwner());
- return BytesValue.EMPTY.equals(converted.getBytesValue()) ? null : converted;
- }
- });
- return convertedFuture;
- }
- };
- @Getter
- private final Function3<Signer, Aer, Long, Future<TxHash>> stakingFunction =
- new Function3<Signer, Aer, Long, Future<TxHash>>() {
- @Override
- public Future<TxHash> apply(final Signer signer, final Aer amount,
- final Long nonce) {
- logger.debug("Staking account with signer: {}, amount: {}, nonce: {}",
- signer.getPrincipal(), amount, nonce);
- final RawTransaction rawTransaction = RawTransaction.newStakeTxBuilder()
- .chainIdHash(contextProvider.get().getChainIdHash())
- .from(signer.getPrincipal())
- .amount(amount)
- .nonce(nonce)
- .build();
- final Transaction signed = signer.sign(rawTransaction);
- return transactionBaseTemplate.getCommitFunction().apply(signed);
- }
- };
- @Getter
- private final Function3<Signer, Aer, Long, Future<TxHash>> unstakingFunction =
- new Function3<Signer, Aer, Long, Future<TxHash>>() {
- @Override
- public Future<TxHash> apply(final Signer signer, final Aer amount,
- final Long nonce) {
- logger.debug("Unstaking account with signer: {}, amount: {}, nonce: {}",
- signer.getPrincipal(), amount, nonce);
- final RawTransaction rawTransaction = RawTransaction.newUnstakeTxBuilder()
- .chainIdHash(contextProvider.get().getChainIdHash())
- .from(signer.getPrincipal())
- .amount(amount)
- .nonce(nonce)
- .build();
- final Transaction signed = signer.sign(rawTransaction);
- return transactionBaseTemplate.getCommitFunction().apply(signed);
- }
- };
- @Getter
- private final Function1<AccountAddress, Future<StakeInfo>> stakingInfoFunction =
- new Function1<AccountAddress, Future<StakeInfo>>() {
- @Override
- public Future<StakeInfo> apply(final AccountAddress accountAddress) {
- logger.debug("Get staking information with address: {}", accountAddress);
- final Rpc.AccountAddress rpcAddress = Rpc.AccountAddress.newBuilder()
- .setValue(accountAddressConverter.convertToRpcModel(accountAddress))
- .build();
- logger.trace("AergoService getStaking arg: {}", rpcAddress);
- final Future<Rpc.Staking> rawFuture = aergoService.getStaking(rpcAddress);
- final Future<StakeInfo> convertedFuture =
- HerajFutures.transform(rawFuture, new Function1<Rpc.Staking, StakeInfo>() {
- @Override
- public StakeInfo apply(final Rpc.Staking rpcStaking) {
- final StakeInfo withoutAddress =
- stakingInfoConverter.convertToDomainModel(rpcStaking);
- return StakeInfo.newBuilder().address(accountAddress)
- .amount(withoutAddress.getAmount())
- .blockNumber(withoutAddress.getBlockNumber())
- .build();
- }
- });
- return convertedFuture;
- }
- };
- @Getter
- private final Function2<Account, RawTransaction, Future<Transaction>> signFunction =
- new Function2<Account, RawTransaction, Future<Transaction>>() {
- @Override
- public Future<Transaction> apply(final Account account,
- final RawTransaction rawTransaction) {
- logger.debug("Sign request with account: {}, rawTx: {}", account.getAddress(),
- rawTransaction);
- if (account instanceof TxSigner) {
- final TxSigner signer = (TxSigner) account;
- final Transaction signed = signer.sign(rawTransaction);
- return HerajFutures.success(signed);
- } else {
- final Transaction domainTransaction = Transaction.newBuilder()
- .rawTransaction(rawTransaction)
- .build();
- final Blockchain.Tx rpcTx = transactionConverter.convertToRpcModel(domainTransaction);
- logger.trace("AergoService signTX arg: {}", rpcTx);
- final Future<Blockchain.Tx> rawFuture = aergoService.signTX(rpcTx);
- final Future<Transaction> convertedFuture =
- HerajFutures.transform(rawFuture, new Function1<Blockchain.Tx, Transaction>() {
- @Override
- public Transaction apply(final Blockchain.Tx rpcTx) {
- return transactionConverter.convertToDomainModel(rpcTx);
- }
- });
- return convertedFuture;
- }
- }
- };
- @Getter
- private final Function2<Account, Transaction, Future<Boolean>> verifyFunction =
- new Function2<Account, Transaction, Future<Boolean>>() {
- @Override
- public Future<Boolean> apply(final Account account,
- final Transaction transaction) {
- logger.debug("Sign verify with account: {}, signedTx: {}", account, transaction);
- final Blockchain.Tx rpcTx = transactionConverter.convertToRpcModel(transaction);
- logger.trace("AergoService verifyTX arg: {}", rpcTx);
- final Future<Rpc.VerifyResult> rawFuture = aergoService.verifyTX(rpcTx);
- final Future<Boolean> convertedFuture =
- HerajFutures.transform(rawFuture, new Function1<Rpc.VerifyResult, Boolean>() {
- @Override
- public Boolean apply(final Rpc.VerifyResult result) {
- if (Rpc.VerifyStatus.VERIFY_STATUS_OK != result.getError()) {
- new TransactionVerificationException(result.getError());
- }
- return true;
- }
- });
- return convertedFuture;
- }
- };
- @Getter
- private final Function4<Signer, String, List<String>, Long,
- Future<TxHash>> voteFunction = new Function4<
- Signer, String, List<String>, Long, Future<TxHash>>() {
- @Override
- public Future<TxHash> apply(final Signer signer, final String voteId,
- final List<String> candidates, final Long nonce) {
- logger.debug("Voting with signer: }, voteId: {}, candidates: {}, nonce: {}",
- signer.getPrincipal(), voteId, candidates, nonce);
- final RawTransaction rawTransaction = RawTransaction.newVoteTxBuilder()
- .chainIdHash(contextProvider.get().getChainIdHash())
- .from(signer.getPrincipal())
- .nonce(nonce)
- .voteId(voteId)
- .candidates(candidates)
- .build();
- final Transaction signed = signer.sign(rawTransaction);
- return transactionBaseTemplate.getCommitFunction().apply(signed);
- }
- };
- @Getter
- private final Function2<String, Integer,
- Future<List<ElectedCandidate>>> listElectedFunction = new Function2<
- String, Integer, Future<List<ElectedCandidate>>>() {
- @Override
- public Future<List<ElectedCandidate>> apply(final String voteId,
- final Integer showCount) {
- logger.debug("Get votes status with voteId: {}, showCount: {}", voteId, showCount);
- final Rpc.VoteParams rpcVoteParams = Rpc.VoteParams.newBuilder()
- .setId(voteId)
- .setCount(showCount)
- .build();
- logger.trace("AergoService getVotes arg: {}", rpcVoteParams);
- final Future<Rpc.VoteList> rawFuture = aergoService.getVotes(rpcVoteParams);
- final Future<List<ElectedCandidate>> convertedFuture =
- HerajFutures.transform(rawFuture,
- new Function1<Rpc.VoteList, List<ElectedCandidate>>() {
- @Override
- public List<ElectedCandidate> apply(final Rpc.VoteList rpcVoteList) {
- final List<ElectedCandidate> electedCandidates = new ArrayList<>();
- for (final Rpc.Vote rpcCandidate : rpcVoteList.getVotesList()) {
- final ElectedCandidate domainElectedCandidate =
- electedCandidateConverter.convertToDomainModel(rpcCandidate);
- electedCandidates.add(domainElectedCandidate);
- }
- return electedCandidates;
- }
- });
- return convertedFuture;
- }
- };
- @Getter
- private final Function1<AccountAddress, Future<AccountTotalVote>> votesOfFunction =
- new Function1<AccountAddress, Future<AccountTotalVote>>() {
- @Override
- public Future<AccountTotalVote> apply(final AccountAddress accountAddress) {
- logger.debug("Get votes with address: {}", accountAddress);
- final Rpc.AccountAddress rpcAddress = Rpc.AccountAddress.newBuilder()
- .setValue(accountAddressConverter.convertToRpcModel(accountAddress))
- .build();
- logger.trace("AergoService getAccountVotes arg: {}", rpcAddress);
- final Future<Rpc.AccountVoteInfo> rawFuture =
- aergoService.getAccountVotes(rpcAddress);
- final Future<AccountTotalVote> convertedFuture =
- HerajFutures.transform(rawFuture,
- new Function1<Rpc.AccountVoteInfo, AccountTotalVote>() {
- @Override
- public AccountTotalVote apply(final Rpc.AccountVoteInfo rpcAccountVoteTotal) {
- return accountTotalVoteConverter.convertToDomainModel(rpcAccountVoteTotal);
- }
- });
- return convertedFuture;
- }
- };
- }