Skip to content
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
Expand Up @@ -143,7 +143,7 @@ private Optional<AccountDetails> infoForAccount(
} else {
final var info = AccountDetails.newBuilder();
info.accountId(account.accountId());
info.contractAccountId(NetworkAdminServiceUtil.asHexedEvmAddress(accountID));
info.contractAccountId(NetworkAdminServiceUtil.asHexedEvmAddress(account.accountId()));
info.deleted(account.deleted());
info.key(account.key());
info.balance(account.tinybarBalance());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.hedera.hapi.node.base.AccountID;
Expand Down Expand Up @@ -219,6 +220,31 @@ void getsResponseIfOkResponse() {
assertEquals(expectedInfo, accountDetailsResponse.accountDetails());
}

@Test
void getsResponseIfQueriedByAlias() {
final var responseHeader = ResponseHeader.newBuilder()
.nodeTransactionPrecheckCode(ResponseCodeEnum.OK)
.build();
final var expectedInfo = getExpectedInfo(
false,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
final var accountStore = mock(ReadableAccountStore.class);

when(context.query()).thenReturn(createGetAccountDetailsQuery(alias));
when(context.createStore(ReadableAccountStore.class)).thenReturn(accountStore);
when(context.createStore(ReadableTokenStore.class)).thenReturn(readableTokenStore);
when(context.createStore(ReadableTokenRelationStore.class)).thenReturn(readableTokenRelStore);
when(accountStore.getAliasedAccountById(alias)).thenReturn(account);

final var response = networkGetAccountDetailsHandler.findResponse(context, responseHeader);
final var accountDetailsResponse = response.accountDetailsOrThrow();
assertEquals(ResponseCodeEnum.OK, accountDetailsResponse.header().nodeTransactionPrecheckCode());
assertEquals(expectedInfo, accountDetailsResponse.accountDetails());
}

@Test
void getsResponseWithTokenRelations() {
givenValidAccount(false, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,28 +169,64 @@ public static HapiContractCallLocal contractCallLocal(
return new HapiContractCallLocal(abi, contract, fn);
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAccountBalance(final String account) {
return new HapiGetAccountBalance(account);
return new HapiGetAccountBalance(account).nodePayment(1234L).noLogging();
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAccountBalance(final String account, final boolean isContract) {
return new HapiGetAccountBalance(account, isContract);
return new HapiGetAccountBalance(account, isContract).nodePayment(1234L).noLogging();
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAutoCreatedAccountBalance(final String sourceKey) {
return new HapiGetAccountBalance(sourceKey, ReferenceType.ALIAS_KEY_NAME);
return new HapiGetAccountBalance(sourceKey, ReferenceType.ALIAS_KEY_NAME)
.nodePayment(1234L)
.noLogging();
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAliasedContractBalance(final String hexedAlias) {
return new HapiGetAccountBalance(hexedAlias, ReferenceType.HEXED_CONTRACT_ALIAS);
return new HapiGetAccountBalance(hexedAlias, ReferenceType.HEXED_CONTRACT_ALIAS)
.nodePayment(1234L)
.noLogging();
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAliasedAccountBalance(final ByteString alias) {
return new HapiGetAccountBalance(alias, ReferenceType.LITERAL_ACCOUNT_ALIAS);
return new HapiGetAccountBalance(alias, ReferenceType.LITERAL_ACCOUNT_ALIAS)
.nodePayment(1234L)
.noLogging();
}

/**
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link #getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public static HapiGetAccountBalance getAccountBalance(final Supplier<String> supplier) {
return new HapiGetAccountBalance(supplier);
return new HapiGetAccountBalance(supplier).nodePayment(1234L).noLogging();
}

public static HapiGetTopicInfo getTopicInfo(final String topic) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,7 @@ protected void assertExpectationsGiven(HapiSpec spec) throws Throwable {
ContractInfo actualInfo = response.getContractGetInfo().getContractInfo();
// Since we don't return token relationships from getContractInfo query, for internal testing
// we are using getAccountDetails query to get token relationships.
if (!relationships.isEmpty()
|| !absentRelationships.isEmpty()
|| expectations.isPresent()
|| registryEntry.isPresent()) {
if (!relationships.isEmpty() || !absentRelationships.isEmpty()) {
final var detailsLookup = getAccountDetails(
String.valueOf(actualInfo.getContractID().getContractNum()))
.payingWith(GENESIS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@
import com.hedera.services.bdd.spec.queries.QueryVerbs;
import com.hedera.services.bdd.spec.transactions.TxnUtils;
import com.hederahashgraph.api.proto.java.AccountID;
import com.hederahashgraph.api.proto.java.ContractID;
import com.hederahashgraph.api.proto.java.CryptoGetAccountBalanceQuery;
import com.hederahashgraph.api.proto.java.CryptoGetInfoQuery;
import com.hederahashgraph.api.proto.java.HederaFunctionality;
import com.hederahashgraph.api.proto.java.Query;
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
import com.hederahashgraph.api.proto.java.ResponseType;
import com.hederahashgraph.api.proto.java.TokenBalance;
import com.hederahashgraph.api.proto.java.TokenID;
import com.hederahashgraph.api.proto.java.Transaction;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand All @@ -34,22 +32,22 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.LongConsumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hiero.base.utility.CommonUtils;
import org.junit.jupiter.api.Assertions;

/**
* Get the balance of an account.
* NOTE: Since we don't return token balances from getAccountBalance query, we are using getAccountDetails query
* if there are any assertions about token balances to get token balances for internal testing.
* Gets the balance of an account from the account details query.
*
* @deprecated This verb no longer submits a {@code CryptoGetAccountBalance} query. New HAPI tests should use
* {@link QueryVerbs#getAccountDetails(String)} with an authorized payer instead.
*/
@Deprecated(forRemoval = true)
public class HapiGetAccountBalance extends HapiQueryOp<HapiGetAccountBalance> {
private static final Logger log = LogManager.getLogger(HapiGetAccountBalance.class);

Expand Down Expand Up @@ -180,7 +178,7 @@ public HapiGetAccountBalance hasId(final AccountID expectedId) {

@Override
public HederaFunctionality type() {
return HederaFunctionality.CryptoGetAccountBalance;
return HederaFunctionality.CryptoGetInfo;
}

@Override
Expand All @@ -190,29 +188,23 @@ protected HapiGetAccountBalance self() {

@Override
protected void assertExpectationsGiven(HapiSpec spec) throws Throwable {
final var balanceResponse = response.getCryptogetAccountBalance();
long actual = balanceResponse.getBalance();
final var actualInfo = response.getCryptoGetInfo().getAccountInfo();
long actual = actualInfo.getBalance();
if (balanceObserver != null) {
balanceObserver.accept(actual);
}
if (verboseLoggingOn) {
String message = String.format(
"Explicit token balances: %s",
response.getCryptogetAccountBalance().getTokenBalancesList());
log.info(message);
}

if (assertAccountIDIsNotAlias) {
final var expectedID = spec.registry()
.getAccountID(spec.registry()
.getKey(aliasKeySource)
.toByteString()
.toStringUtf8());
assertEquals(expectedID, response.getCryptogetAccountBalance().getAccountID());
assertEquals(expectedID, actualInfo.getAccountID());
}

if (expectedId != null) {
assertEquals(expectedId, response.getCryptogetAccountBalance().getAccountID(), "Wrong account id");
assertEquals(expectedId, actualInfo.getAccountID(), "Wrong account id");
}

if (expectedTinybarCondition.isPresent()) {
Expand All @@ -226,22 +218,31 @@ protected void assertExpectationsGiven(HapiSpec spec) throws Throwable {
assertEquals(expected.get().longValue(), actual, "Wrong balance!");
}

// Since we don't support token balances from getAccountBalance query, for internal testing
// we are using getAccountDetails query to get token balances.
if (!expectedTokenBalances.isEmpty() || tokenBalanceObservers.isPresent() || expectedTokenConditions != null) {
final var detailsLookup = QueryVerbs.getAccountDetails(toEntityId(balanceResponse.getAccountID()))
final var accountId = actualInfo.getAccountID();
final var detailsLookup = QueryVerbs.getAccountDetails(
accountId.getShardNum() + "." + accountId.getRealmNum() + "." + accountId.getAccountNum())
.payingWith(GENESIS);
allRunFor(spec, detailsLookup);
final var response = detailsLookup.getResponse();
if (verboseLoggingOn) {
String message = String.format(
"Explicit token balances: %s",
detailsLookup
.getResponse()
.getAccountDetails()
.getAccountDetails()
.getTokenRelationshipsList());
log.info(message);
}
Map<TokenID, Pair<Long, Integer>> actualTokenBalances =
response.getAccountDetails().getAccountDetails().getTokenRelationshipsList().stream()
.map(tr -> TokenBalance.newBuilder()
.setTokenId(tr.getTokenId())
.setBalance(tr.getBalance())
.setDecimals(tr.getDecimals())
.build())
detailsLookup
.getResponse()
.getAccountDetails()
.getAccountDetails()
.getTokenRelationshipsList()
.stream()
.collect(Collectors.toMap(
TokenBalance::getTokenId, tb -> Pair.of(tb.getBalance(), tb.getDecimals())));
tr -> tr.getTokenId(), tr -> Pair.of(tr.getBalance(), tr.getDecimals())));
if (expectedTokenConditions != null) {
expectedTokenConditions.forEach((key, value) -> {
final var tokenId = asTokenId(key, spec);
Expand Down Expand Up @@ -302,12 +303,13 @@ protected void assertExpectationsGiven(HapiSpec spec) throws Throwable {

@Override
protected void processAnswerOnlyResponse(@NonNull final HapiSpec spec) {
final var status = response.getCryptogetAccountBalance().getHeader().getNodeTransactionPrecheckCode();
final var infoResponse = response.getCryptoGetInfo();
final var status = infoResponse.getHeader().getNodeTransactionPrecheckCode();
if (status == ResponseCodeEnum.ACCOUNT_DELETED) {
String message = String.format("%s%s was actually deleted!", spec.logPrefix(), repr);
log.info(message);
} else {
long balance = response.getCryptogetAccountBalance().getBalance();
long balance = infoResponse.getAccountInfo().getBalance();
long TINYBARS_PER_HBAR = 100_000_000L;
long hBars = balance / TINYBARS_PER_HBAR;
if (!loggingOff) {
Expand All @@ -329,57 +331,59 @@ protected Query queryFor(
@NonNull final HapiSpec spec,
@NonNull final Transaction payment,
@NonNull final ResponseType responseType) {
return getAccountBalanceQuery(spec, payment, responseType == ResponseType.COST_ANSWER);
return getAccountInfoQuery(spec, payment, responseType == ResponseType.COST_ANSWER);
}

private Query getAccountBalanceQuery(HapiSpec spec, Transaction payment, boolean costOnly) {
private Query getAccountInfoQuery(HapiSpec spec, Transaction payment, boolean costOnly) {
if (entityFn.isPresent()) {
account = entityFn.get().get();
repr = account;
}

Consumer<CryptoGetAccountBalanceQuery.Builder> config;
AccountID target;
if (isContract || spec.registry().hasContractId(account)) {
config = b -> b.setContractID(TxnUtils.asContractId(account, spec));
final var contractId = TxnUtils.asContractId(account, spec);
final var targetBuilder =
AccountID.newBuilder().setShardNum(contractId.getShardNum()).setRealmNum(contractId.getRealmNum());
if (contractId.hasEvmAddress()) {
targetBuilder.setAlias(contractId.getEvmAddress());
} else {
targetBuilder.setAccountNum(contractId.getContractNum());
}
target = targetBuilder.build();
} else if (referenceType == ReferenceType.HEXED_CONTRACT_ALIAS) {
final var cid = ContractID.newBuilder()
target = AccountID.newBuilder()
.setShardNum(spec.shard())
.setRealmNum(spec.realm())
.setEvmAddress(ByteString.copyFrom(CommonUtils.unhex(literalHexedAlias)))
.setAlias(TxnUtils.asLiteralEvmAddress(literalHexedAlias))
.build();
config = b -> b.setContractID(cid);
} else {
AccountID id;
if (referenceType == ReferenceType.REGISTRY_NAME) {
id = TxnUtils.asId(account, spec);
target = TxnUtils.asId(account, spec);
} else if (referenceType == ReferenceType.LITERAL_ACCOUNT_ALIAS) {
id = AccountID.newBuilder()
target = AccountID.newBuilder()
.setShardNum(spec.shard())
.setRealmNum(spec.realm())
.setAlias(rawAlias)
.build();
} else {
id = spec.registry().keyAliasIdFor(spec, aliasKeySource);
target = spec.registry().keyAliasIdFor(spec, aliasKeySource);
}
config = b -> b.setAccountID(id);
}
CryptoGetAccountBalanceQuery.Builder query = CryptoGetAccountBalanceQuery.newBuilder()
.setHeader(costOnly ? answerCostHeader(payment) : answerHeader(payment));
config.accept(query);
return Query.newBuilder().setCryptogetAccountBalance(query).build();
final var query = CryptoGetInfoQuery.newBuilder()
.setHeader(costOnly ? answerCostHeader(payment) : answerHeader(payment))
.setAccountID(target)
.build();
return Query.newBuilder().setCryptoGetInfo(query).build();
}

@Override
protected boolean needsPayment() {
return false;
return true;
}

@Override
protected MoreObjects.ToStringHelper toStringHelper() {
return super.toStringHelper().add("account", account);
}

private String toEntityId(AccountID accountID) {
return accountID.getShardNum() + "." + accountID.getRealmNum() + "." + accountID.getAccountNum();
}
}
Loading
Loading