Skip to content

Commit

Permalink
Merge pull request #314 from Concordium/Energy-to-ccd
Browse files Browse the repository at this point in the history
Convenience functions issue #272
  • Loading branch information
magnusbechwind authored Mar 6, 2024
2 parents 76951be + 9c5d8ce commit 799290f
Show file tree
Hide file tree
Showing 14 changed files with 573 additions and 40 deletions.
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`.
- Fixed a bug in `CustomEvent`. Removed unnecessary `tag` field.
- Added `Web3IdProof` class with `getWeb3IdProof` method to create Presentations. (And supporting classes)
- Fixed an issue where `ConcordiumHdWallet.fromSeedPhrase` always produced an invalid seed as hex.
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.CurrencyConverter;
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 = CurrencyConverter.energyToEuro(usedEnergy, parameters).asBigDecimal(6);
BigDecimal ccd = CurrencyConverter.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.CurrencyConverter;
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 = CurrencyConverter.energyToEuro(usedEnergy, parameters).asBigDecimal(6);
BigDecimal ccd = CurrencyConverter.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
137 changes: 137 additions & 0 deletions concordium-sdk/src/main/java/com/concordium/sdk/CurrencyConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
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.ConversionResult;
import com.concordium.sdk.types.UInt64;

import static com.concordium.sdk.types.ConversionResult.*;

/**
* Utility class for converting between {@link CCDAmount}, {@link Energy} and Euros.
* Represents converted values using {@link ConversionResult} to ensure precision.
*/
public class CurrencyConverter {

/**
* 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 ConversionResult} corresponding to the euro value of {@link Energy}.
*/
public static ConversionResult<EUR> energyToEuro(Energy energy, ChainParameters parameters) {
ConversionResult<NRG> energyFraction = from(energy.getValue(), UInt64.from(1));
return energyToEuro(energyFraction, parameters);
}

/**
* Converts {@link ConversionResult} representing {@link Energy} to euro using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link ConversionResult} representing an amount of {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link ConversionResult} corresponding to the euro value of {@link Energy}.
*/
public static ConversionResult<EUR> energyToEuro(ConversionResult<NRG> energy, ChainParameters parameters) {
ConversionResult<ConversionRate> euroPerEnergy = from(parameters.getEuroPerEnergy());
return energy.mult(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 ConversionResult} corresponding to the micro CCD value of {@link Energy}.
*/
public static ConversionResult<microCCD> energyToMicroCCD(Energy energy, ChainParameters parameters) {
ConversionResult<NRG> energyFraction = from(energy.getValue(), UInt64.from(1));
return energyToMicroCCD(energyFraction, parameters);
}

/**
* Converts {@link ConversionResult} representing {@link Energy} to micro CCD using exchange rate from the provided {@link ChainParameters}.
*
* @param energy {@link ConversionResult} representing an amount of {@link Energy} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link ConversionResult} corresponding to the micro CCD value of {@link Energy}.
*/
public static ConversionResult<microCCD> energyToMicroCCD(ConversionResult<NRG> energy, ChainParameters parameters) {
ConversionResult<EUR> 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 ConversionResult} corresponding to the euro value of {@link CCDAmount}.
*/
public static ConversionResult<EUR> microCCDToEuro(CCDAmount ccdAmount, ChainParameters parameters) {
ConversionResult<microCCD> ccd = from(ccdAmount.getValue(), UInt64.from(1));
return microCCDToEuro(ccd, parameters);
}

/**
* Converts {@link ConversionResult} representing {@link CCDAmount} to euros using exchange rate from the provided {@link ChainParameters}.
*
* @param ccd {@link ConversionResult} representing {@link CCDAmount} to convert.
* @param parameters {@link ChainParameters} with exchange rate used for conversion.
* @return {@link ConversionResult} corresponding to the euro value of {@link CCDAmount}.
*/
public static ConversionResult<EUR> microCCDToEuro(ConversionResult<microCCD> ccd, ChainParameters parameters) {
ConversionResult<ConversionRate> microCCDPerEuro = from(parameters.getMicroCCDPerEuro());
return ccd.div(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 ConversionResult} corresponding to the energy value of {@link CCDAmount}.
*/
public static ConversionResult<NRG> ccdToEnergy(CCDAmount ccdAmount, ChainParameters parameters) {
ConversionResult<microCCD> ccd = from(ccdAmount.getValue(), UInt64.from(1));
return ccdToEnergy(ccd, parameters);
}

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

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

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

}
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

0 comments on commit 799290f

Please sign in to comment.