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

Convenience functions issue #272 #314

Merged
merged 18 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## Unreleased changes
- Removed unnecessary `amount` parameter from `InvokeInstanceRequest`.
- Added utility functions for converting between `CCDAmount` and `Energy`. Present in utility class `Converter`.
- Make the `energy` parameter for invoking an instance `Optional`.
- Parse the underlying reject reasons into `AccountTransactionDetails`.
- Introduced Cis2Client for interfacing with CIS2 compliant smart contracts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@

import com.concordium.sdk.ClientV2;
import com.concordium.sdk.Connection;
import com.concordium.sdk.Converter;
import com.concordium.sdk.crypto.ed25519.ED25519SecretKey;
import com.concordium.sdk.exceptions.ClientInitializationException;
import com.concordium.sdk.requests.AccountQuery;
import com.concordium.sdk.requests.BlockQuery;
import com.concordium.sdk.requests.smartcontracts.Energy;
import com.concordium.sdk.requests.smartcontracts.InvokeInstanceRequest;
import com.concordium.sdk.responses.blockitemstatus.FinalizedBlockItem;
import com.concordium.sdk.responses.chainparameters.ChainParameters;
import com.concordium.sdk.responses.modulelist.ModuleRef;
import com.concordium.sdk.responses.smartcontracts.InvokeInstanceResult;
import com.concordium.sdk.transactions.*;
import com.concordium.sdk.transactions.smartcontracts.SchemaParameter;
import com.concordium.sdk.types.AccountAddress;
import com.concordium.sdk.types.ContractAddress;
import com.concordium.sdk.types.Nonce;
import com.concordium.sdk.types.UInt64;
import com.concordium.sdk.types.*;
import lombok.var;
import picocli.CommandLine;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Optional;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -130,6 +133,20 @@ private void handleInit(ClientV2 client, Nonce nonce) {
}

private void handleMethod(ClientV2 client, Nonce nonce, SchemaParameter parameter) {

// Estimate energy used by transaction.
InvokeInstanceRequest invokeInstanceRequest = InvokeInstanceRequest.from(BlockQuery.LAST_FINAL,
CONTRACT_ADDRESS,
parameter,
Optional.empty());
InvokeInstanceResult invokeInstanceResult = client.invokeInstance(invokeInstanceRequest);
Energy usedEnergy = invokeInstanceResult.getUsedEnergy();
ChainParameters parameters = client.getChainParameters(BlockQuery.LAST_FINAL);
// Convert to Euro and CCD using ChainParameters from the best block and utility methods in the Converter class.
BigDecimal euros = Converter.energyToEuro(usedEnergy, parameters).asBigDecimal(6);
BigDecimal ccd = Converter.energyToMicroCCD(usedEnergy, parameters).asBigDecimal(6);
System.out.println("Price of transaction is: " + usedEnergy + " = " + euros + " euros = " + ccd + " micro CCD");

UpdateContract payload = UpdateContract.from(CONTRACT_ADDRESS, parameter);
UpdateContractTransaction transaction = TransactionFactory.newUpdateContract()
.sender(AccountAddress.from(SENDER_ADDRESS))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import com.concordium.sdk.ClientV2;
import com.concordium.sdk.Connection;
import com.concordium.sdk.Converter;
import com.concordium.sdk.crypto.ed25519.ED25519SecretKey;
import com.concordium.sdk.requests.AccountQuery;
import com.concordium.sdk.requests.BlockQuery;
import com.concordium.sdk.requests.smartcontracts.Energy;
import com.concordium.sdk.requests.smartcontracts.InvokeInstanceRequest;
import com.concordium.sdk.responses.blockitemstatus.FinalizedBlockItem;
import com.concordium.sdk.responses.chainparameters.ChainParameters;
import com.concordium.sdk.responses.modulelist.ModuleRef;
import com.concordium.sdk.responses.smartcontracts.InvokeInstanceResult;
import com.concordium.sdk.transactions.*;
import com.concordium.sdk.transactions.smartcontracts.SchemaParameter;
import com.concordium.sdk.types.AccountAddress;
Expand All @@ -16,6 +21,7 @@
import lombok.var;
import picocli.CommandLine;

import java.math.BigDecimal;
import java.net.URL;
import java.util.Optional;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -147,6 +153,19 @@ private void handleInit(ClientV2 client, Nonce nonce) {
}

private void handleMethod(ClientV2 client, Nonce nonce, SchemaParameter parameter) {
// Estimate energy used by transaction.
InvokeInstanceRequest invokeInstanceRequest = InvokeInstanceRequest.from(BlockQuery.LAST_FINAL,
CONTRACT_ADDRESS,
parameter,
Optional.empty());
InvokeInstanceResult invokeInstanceResult = client.invokeInstance(invokeInstanceRequest);
Energy usedEnergy = invokeInstanceResult.getUsedEnergy();
ChainParameters parameters = client.getChainParameters(BlockQuery.LAST_FINAL);
// Convert to Euro and CCD using ChainParameters from the best block and utility methods in the Converter class.
BigDecimal euros = Converter.energyToEuro(usedEnergy, parameters).asBigDecimal(6);
BigDecimal ccd = Converter.energyToMicroCCD(usedEnergy, parameters).asBigDecimal(6);
System.out.println("Price of transaction is: " + usedEnergy + " = " + euros + " euros = " + ccd + " micro CCD");

UpdateContract payload = UpdateContract.from(CONTRACT_ADDRESS, parameter);
UpdateContractTransaction transaction = TransactionFactory.newUpdateContract()
.sender(AccountAddress.from(SENDER_ADDRESS))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ public InvokeInstanceResult invokeInstance(InvokeInstanceRequest request) {
grpcRequest.setInvoker(to(request.getInvoker()));
}
grpcRequest.setInstance(to(request.getInstance()))
.setAmount(to(request.getAmount()))
.setAmount(to(CCDAmount.from(0)))
.setEntrypoint(to(request.getEntrypoint()))
.setParameter(to(request.getParameter()));
if (request.getEnergy().isPresent()) {
Expand Down
156 changes: 156 additions & 0 deletions concordium-sdk/src/main/java/com/concordium/sdk/Converter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package com.concordium.sdk;

import com.concordium.sdk.requests.smartcontracts.Energy;
import com.concordium.sdk.responses.chainparameters.ChainParameters;
import com.concordium.sdk.transactions.CCDAmount;
import com.concordium.sdk.types.BigFraction;
import com.concordium.sdk.types.UInt64;

import java.math.BigInteger;

/**
* Utility class for converting between {@link CCDAmount}, {@link Energy} and Euros.
* Represents converted values using {@link BigFraction} to ensure precision.
*/
public class Converter {
magnusbechwind marked this conversation as resolved.
Show resolved Hide resolved

/**
* Converts {@link Energy} to euro using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the euro value of {@link Energy}.
*/
public static BigFraction energyToEuro(Energy energy, ChainParameters parameters) {
BigFraction energyFraction = BigFraction.from(energy.getValue(), UInt64.from(1));
return energyToEuro(energyFraction, parameters);
}

/**
* Converts {@link BigFraction} representing {@link Energy} to euro using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link BigFraction} representing an amount of {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the euro value of {@link Energy}.
*/
public static BigFraction energyToEuro(BigFraction energy, ChainParameters parameters) {
magnusbechwind marked this conversation as resolved.
Show resolved Hide resolved
BigFraction euroPerEnergy = BigFraction.from(parameters.getEuroPerEnergy());
return mult(energy, euroPerEnergy);
}

/**
* Converts {@link Energy} to micro CCD using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the micro CCD value of {@link Energy}.
*/
public static BigFraction energyToMicroCCD(Energy energy, ChainParameters parameters) {
BigFraction energyFraction = BigFraction.from(energy.getValue(), UInt64.from(1));
return energyToMicroCCD(energyFraction, parameters);
}

/**
* Converts {@link BigFraction} representing {@link Energy} to micro CCD using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link BigFraction} representing an amount of {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the micro CCD value of {@link Energy}.
*/
public static BigFraction energyToMicroCCD(BigFraction energy, ChainParameters parameters) {
BigFraction euros = energyToEuro(energy, parameters);
return euroToMicroCCD(euros, parameters);
}

/**
* Converts {@link CCDAmount} to euros using exchange rate from the provided {@link ChainParameters}.
*
* @param ccdAmount {@link CCDAmount} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the euro value of {@link CCDAmount}.
*/
public static BigFraction microCCDToEuro(CCDAmount ccdAmount, ChainParameters parameters) {
BigFraction ccd = BigFraction.from(ccdAmount.getValue(), UInt64.from(1));
return microCCDToEuro(ccd, parameters);
}

/**
* Converts {@link BigFraction} representing {@link CCDAmount} to euros using exchange rate from the provided {@link ChainParameters}.
*
* @param ccd {@link BigFraction} representing {@link CCDAmount} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the euro value of {@link CCDAmount}.
*/
public static BigFraction microCCDToEuro(BigFraction ccd, ChainParameters parameters) {
BigFraction microCCDPerEuro = BigFraction.from(parameters.getMicroCCDPerEuro());
return div(ccd, microCCDPerEuro);
}

/**
* Converts {@link CCDAmount} to energy using exchange rate from the provided {@link ChainParameters}.
*
* @param ccdAmount{@link CCDAmount} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the energy value of {@link CCDAmount}.
*/
public static BigFraction ccdToEnergy(CCDAmount ccdAmount, ChainParameters parameters) {
BigFraction ccd = BigFraction.from(ccdAmount.getValue(), UInt64.from(1));
return ccdToEnergy(ccd, parameters);
}

/**
* Converts {@link BigFraction} representing {@link CCDAmount} to energy using exchange rate from the provided {@link ChainParameters}.
*
* @param ccdAmount {@link BigFraction} representing {@link CCDAmount} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the energy value of {@link CCDAmount}.
*/
public static BigFraction ccdToEnergy(BigFraction ccdAmount, ChainParameters parameters) {
BigFraction euros = microCCDToEuro(ccdAmount, parameters);
return euroToEnergy(euros, parameters);
}

/**
* Converts {@link BigFraction} representing an amount of euros to micro CCD using exchange rate from the provided {@link ChainParameters}.
*
* @param euros {@link BigFraction} representing amount of euros to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the micro CCD value of the input.
*/
public static BigFraction euroToMicroCCD(BigFraction euros, ChainParameters parameters) {
BigFraction microCCDPerEuro = BigFraction.from(parameters.getMicroCCDPerEuro());
return mult(euros, microCCDPerEuro);
}

/**
* Converts {@link BigFraction} representing an amount of euros to energy using exchange rate from the provided {@link ChainParameters}.
*
* @param euros {@link BigFraction} representing amount of euros to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link BigFraction} corresponding to the energy value of the input.
*/
public static BigFraction euroToEnergy(BigFraction euros, ChainParameters parameters) {
BigFraction euroPerEnergy = BigFraction.from(parameters.getEuroPerEnergy());
return div(euros,euroPerEnergy);
}

/**
* Helper function for multiplying {@link BigFraction}s used during conversions.
* Calculates a*c/b*d for input a/b, c/d.
*/
private static BigFraction mult(BigFraction a, BigFraction b) {
BigInteger numerator = a.getNumerator().multiply(b.getNumerator());
BigInteger denominator = a.getDenominator().multiply(b.getDenominator());
return BigFraction.from(numerator, denominator);
}

/**
* Helper function for dividing {@link BigFraction}s used during conversions.
* Calculates a*d/b*c for input a/b, c/d.
*/
private static BigFraction div(BigFraction a, BigFraction b) {
BigInteger numerator = a.getNumerator().multiply(b.getDenominator());
BigInteger denominator = a.getDenominator().multiply(b.getNumerator());
return BigFraction.from(numerator, denominator);
}
magnusbechwind marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
package com.concordium.sdk.cis2;

import com.concordium.sdk.ClientV2;
import com.concordium.sdk.cis2.events.Cis2Event;
import com.concordium.sdk.cis2.events.Cis2EventWithMetadata;
import com.concordium.sdk.requests.AccountQuery;
import com.concordium.sdk.requests.BlockQuery;
import com.concordium.sdk.requests.smartcontracts.Energy;
import com.concordium.sdk.requests.smartcontracts.InvokeInstanceRequest;
import com.concordium.sdk.responses.blockitemstatus.FinalizedBlockItem;
import com.concordium.sdk.responses.blockitemsummary.Summary;
import com.concordium.sdk.responses.blockitemsummary.Type;
import com.concordium.sdk.responses.blocksatheight.BlocksAtHeightRequest;
import com.concordium.sdk.responses.smartcontracts.ContractTraceElement;
import com.concordium.sdk.responses.smartcontracts.ContractTraceElementType;
import com.concordium.sdk.responses.transactionstatus.ContractUpdated;
import com.concordium.sdk.responses.transactionstatus.Outcome;
import com.concordium.sdk.responses.transactionstatus.TransactionResultEventType;
import com.concordium.sdk.transactions.*;
import com.concordium.sdk.types.*;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.val;
import lombok.var;

import java.util.*;
import java.util.stream.Collectors;

/**
* A client dedicated to the CIS2 <a href="https://proposals.concordium.software/CIS/cis-2.html">specification</a>.
Expand Down Expand Up @@ -112,7 +102,7 @@ public Map<BalanceQuery, TokenAmount> balanceOf(BalanceQuery... queries) {
val listOfQueries = Arrays.asList(queries);
val parameter = SerializationUtils.serializeBalanceOfParameter(listOfQueries);
val endpoint = ReceiveName.from(contractName, "balanceOf");
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, CCDAmount.from(0), endpoint, parameter, Optional.empty()));
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, endpoint, parameter, Optional.empty()));
if (result.getOutcome() == Outcome.REJECT) {
throw new RuntimeException("balanceOf failed: " + result.getRejectReason().toString());
}
Expand All @@ -134,7 +124,7 @@ public Map<OperatorQuery, Boolean> operatorOf(OperatorQuery... queries) {
val listOfQueries = Arrays.asList(queries);
val parameter = SerializationUtils.serializeOperatorOfParameter(listOfQueries);
val endpoint = ReceiveName.from(contractName, "operatorOf");
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, CCDAmount.from(0), endpoint, parameter, Optional.empty()));
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, endpoint, parameter, Optional.empty()));
if (result.getOutcome() == Outcome.REJECT) {
throw new RuntimeException("operatorOf failed: " + result.getRejectReason().toString());
}
Expand All @@ -156,7 +146,7 @@ public Map<TokenId, TokenMetadata> tokenMetadata(TokenId... tokenIds) {
val listOfQueries = Arrays.asList(tokenIds);
val parameter = SerializationUtils.serializeTokenIds(listOfQueries);
val endpoint = ReceiveName.from(contractName, "tokenMetadata");
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, CCDAmount.from(0), endpoint, parameter, Optional.empty()));
val result = this.client.invokeInstance(InvokeInstanceRequest.from(BlockQuery.LAST_FINAL, this.contractAddress, endpoint, parameter, Optional.empty()));
if (result.getOutcome() == Outcome.REJECT) {
throw new RuntimeException("tokenMetadata failed: " + result.getRejectReason().toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class Energy {

@Override
public String toString() {
return this.value.getValue() + " NRG";
return this.value.toString() + " NRG";
}

public static Energy from(com.concordium.grpc.v2.Energy energy) {
Expand All @@ -26,4 +26,8 @@ public static Energy from(com.concordium.grpc.v2.Energy energy) {
public static Energy from(UInt64 value) {
return new Energy(value);
}
public static Energy from(String val) {
return Energy.from(UInt64.from(val));
}

}
Loading
Loading