diff --git a/CHANGELOG.md b/CHANGELOG.md
index 918352301..6f2c3ea08 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
+## 11.0.0
+
+- Support for Protocol 9
+- Added `ProtocolVersion.V9` corresponding to Protocol version 9
+- Added `tokens` field to `AccountInfo`, containing list of related protocol level tokens
+- Added new account transaction, `TokenUpdate`, used to execute protocol level tokens operations
+- Added `TokenOperation` interface for protocol level tokens operations
+- Added `TransferTokenOperation` implementing protocol level token transfer
+- Added protocol level token transfer example, see `SendTokenTransfer` in `concordium-sdk-examples`
+- Added `tokenUpdate` result to `AccountTransactionDetails`
+- Added `createPltUpdate` authorization to `AuthorizationsV1`
+- Added `RejectReasonTokenUpdateTransactionFailed` and `RejectReasonNotExistentTokenId` transaction reject reasons
+- Added `CborMapper` singleton providing Jackson CBOR object mapper
+- Fixed having the Lombok library transitive
+
## 10.0.1
- Added `getPassiveDelegationInfo` endpoint providing information
diff --git a/README.md b/README.md
index a1ca0aa01..3b8401669 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@ The `ClientV2` must be initialized with a `Connection` which holds information o
Connection connection = Connection.newBuilder()
.host(${node_host})
.port(${node_port})
+ .useTLS(TLSConfig.auto()) // If the node is under HTTPS
.build();
ClientV2 client = ClientV2.from(connection);
```
diff --git a/concordium-android-sdk/pom.xml b/concordium-android-sdk/pom.xml
index 165f165fc..b527b2e55 100644
--- a/concordium-android-sdk/pom.xml
+++ b/concordium-android-sdk/pom.xml
@@ -5,11 +5,10 @@
com.concordium.sdk
concordium-sdk-base
- 11.0.0-SNAPSHOT
+ 11.0.0
concordium-android-sdk
- com.concordium.sdk
aar
@@ -33,57 +32,54 @@
io.grpc
grpc-netty-shaded
- 1.40.1
commons-io
commons-io
- 2.11.0
commons-codec
commons-codec
- 1.15
org.projectlombok
lombok
- 1.18.26
io.grpc
grpc-protobuf
- 1.40.1
io.grpc
grpc-okhttp
- 1.60.0
io.grpc
grpc-stub
- 1.60.0
com.fasterxml.jackson.core
jackson-core
- 2.10.1
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-cbor
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
- 2.10.1
com.fasterxml.jackson.datatype
jackson-datatype-jdk8
- 2.10.1
org.bitcoinj
bitcoinj-core
- 0.16.2
com.google.protobuf
@@ -94,7 +90,6 @@
org.apache.commons
commons-lang3
- 3.14.0
diff --git a/concordium-base b/concordium-base
index 6f6d1088c..f69906f2e 160000
--- a/concordium-base
+++ b/concordium-base
@@ -1 +1 @@
-Subproject commit 6f6d1088cd8660abe7d9e4a1274a817032313a57
+Subproject commit f69906f2e386444d85ab99f38951869cedf4be67
diff --git a/concordium-sdk-examples/pom.xml b/concordium-sdk-examples/pom.xml
index 4c2a7e40f..0319056e5 100644
--- a/concordium-sdk-examples/pom.xml
+++ b/concordium-sdk-examples/pom.xml
@@ -23,8 +23,7 @@
com.concordium.sdk
concordium-sdk
- 11.0.0-SNAPSHOT
- compile
+ 11.0.0
org.projectlombok
diff --git a/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/SendTokenTransfer.java b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/SendTokenTransfer.java
new file mode 100644
index 000000000..979998af5
--- /dev/null
+++ b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/SendTokenTransfer.java
@@ -0,0 +1,102 @@
+package com.concordium.sdk.examples;
+
+import com.concordium.sdk.ClientV2;
+import com.concordium.sdk.Connection;
+import com.concordium.sdk.TLSConfig;
+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.responses.blockitemstatus.FinalizedBlockItem;
+import com.concordium.sdk.transactions.*;
+import com.concordium.sdk.transactions.tokens.CborMemo;
+import com.concordium.sdk.transactions.tokens.TaggedTokenHolderAccount;
+import com.concordium.sdk.transactions.tokens.TokenOperationAmount;
+import com.concordium.sdk.transactions.tokens.TransferTokenOperation;
+import com.concordium.sdk.types.AccountAddress;
+import lombok.var;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+
+import java.math.BigDecimal;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Optional;
+import java.util.concurrent.Callable;
+
+@Command(name = "SendTokenTransfer", mixinStandardHelpOptions = true)
+public class SendTokenTransfer implements Callable {
+ @Option(
+ names = {"--endpoint"},
+ description = "GRPC interface of the node.",
+ defaultValue = "https://grpc.devnet-plt-beta.concordium.com:20000")
+ private String endpoint;
+
+ @Option(
+ names = {"--timeout"},
+ description = "GRPC request timeout in milliseconds.",
+ defaultValue = "100000")
+ private int timeout;
+
+ @Override
+ public Integer call() throws MalformedURLException, ClientInitializationException {
+ var endpointUrl = new URL(this.endpoint);
+
+ Connection connection = Connection.newBuilder()
+ .host(endpointUrl.getHost())
+ .port(endpointUrl.getPort())
+ .useTLS(TLSConfig.auto())
+ .build();
+
+ String tokenSymbol = "TestLists";
+ TokenOperationAmount amount = new TokenOperationAmount(
+ new BigDecimal("0.01"),
+ 10
+ );
+ AccountAddress sender = AccountAddress.from("4m9AzH7oeq2LNZpmBu3uW9KJEimevgBMD79PhTMxJeYVmtRdxR");
+ AccountAddress receiver = AccountAddress.from("386L81BpBVrm2cDrnjEqpaGcuveC8FgiH5ZBxSVdvto4ydVFLX");
+ Expiry expiry = Expiry.createNew().addMinutes(5);
+
+ TransactionSigner signer = TransactionSigner.from(
+ SignerEntry.from(Index.from(0), Index.from(0),
+ ED25519SecretKey
+ .from("ad42d4f5122f4cc758c27b9c776f2d7635f30e55acb8697bb7a97edb3d7f0d88")));
+
+ var client = ClientV2.from(connection);
+ var senderInfo = client.getAccountInfo(BlockQuery.BEST, AccountQuery.from(sender));
+ var nonce = senderInfo.getNonce();
+ var txnHash = client.sendTransaction(
+ TransactionFactory
+ .newTokenUpdate()
+ .sender(sender)
+ .payload(
+ TokenUpdate
+ .builder()
+ .tokenSymbol(tokenSymbol)
+ .operation(
+ TransferTokenOperation
+ .builder()
+ .recipient(new TaggedTokenHolderAccount(receiver))
+ .amount(amount)
+ .memo(CborMemo.from("You must see a multi-byte white woman scientist emoji: 👩🏻🔬"))
+ .build()
+ )
+ .build()
+ )
+ .nonce(nonce)
+ .expiry(expiry)
+ .signer(signer)
+ .build()
+ );
+ System.out.println(txnHash);
+ Optional finalizedBlockItem = client.waitUntilFinalized(txnHash, this.timeout);
+ System.out.println(finalizedBlockItem);
+ return 0;
+ }
+
+ public static void main(String[] args) {
+ int exitCode = new CommandLine(new SendTokenTransfer()).execute(args);
+ System.exit(exitCode);
+ }
+}
diff --git a/concordium-sdk/pom.xml b/concordium-sdk/pom.xml
index 566d90ff5..547765a47 100644
--- a/concordium-sdk/pom.xml
+++ b/concordium-sdk/pom.xml
@@ -5,12 +5,11 @@
4.0.0
- com.concordium.sdk
+ com.concordium.sdk
concordium-sdk-base
- 11.0.0-SNAPSHOT
+ 11.0.0
- com.concordium.sdk
concordium-sdk
concordium-sdk
@@ -26,15 +25,12 @@
UTF-8
- 1.8
- 1.8
org.bitcoinj
bitcoinj-core
- 0.16.2
com.google.protobuf
@@ -45,75 +41,70 @@
io.grpc
grpc-netty-shaded
- 1.40.1
io.grpc
grpc-protobuf
- 1.40.1
io.grpc
grpc-testing
- 1.40.1
test
io.grpc
grpc-stub
- 1.40.1
javax.annotation
javax.annotation-api
- 1.2
junit
junit
- 4.12
test
org.projectlombok
lombok
- 1.18.26
+ provided
com.fasterxml.jackson.core
- jackson-databind
- 2.11.1
+ jackson-core
- commons-codec
- commons-codec
- 1.15
+ com.fasterxml.jackson.core
+ jackson-databind
- commons-io
- commons-io
- 2.11.0
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-cbor
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
- 2.13.2
com.fasterxml.jackson.datatype
jackson-datatype-jdk8
- 2.13.3
+
+
+ commons-codec
+ commons-codec
+
+
+ commons-io
+ commons-io
org.mockito
mockito-core
- 3.3.3
test
org.apache.commons
commons-lang3
- 3.14.0
@@ -359,6 +350,11 @@
maven-compiler-plugin
3.8.0
+
+ 1.8
+ 1.8
+ false
+
maven-surefire-plugin
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2MapperExtensions.java b/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2MapperExtensions.java
index 2953c7362..069a90c18 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2MapperExtensions.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2MapperExtensions.java
@@ -1245,6 +1245,14 @@ static Summary to(BlockItemSummary blockItemSummary) {
.chainUpdateDetails(details)
.build());
break;
+ case TOKEN_CREATION:
+ val tokenCreationDetails = blockItemSummary.getTokenCreation();
+ summary.details(Details
+ .builder()
+ .type(Type.TOKEN_CREATION)
+ .tokenCreationDetails(tokenCreationDetails)
+ .build());
+ break;
case DETAILS_NOT_SET:
throw new IllegalArgumentException("Unrecognized block item summary");
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/ProtocolVersion.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/ProtocolVersion.java
index e26331de0..530a65dfe 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/ProtocolVersion.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/ProtocolVersion.java
@@ -6,33 +6,37 @@
public enum ProtocolVersion {
V1,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P2.txt
+ * Protocol Version: 2
*/
V2,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P3.txt
+ * Protocol Version: 3
*/
V3,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P4.txt
+ * Protocol Version: 4
*/
V4,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P5.txt
+ * Protocol Version: 5
*/
V5,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P6.txt
+ * Protocol Version: 6
*/
V6,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P7.txt
+ * Protocol Version: 7
*/
V7,
/**
- * https://github.com/Concordium/concordium-update-proposals/blob/main/updates/P8.txt
+ * Protocol Version: 8
*/
V8,
+ /**
+ * Protocol Version: 9
+ */
+ V9,
;
/**
@@ -59,6 +63,8 @@ public static ProtocolVersion parse(com.concordium.grpc.v2.ProtocolVersion proto
return V7;
case PROTOCOL_VERSION_8:
return V8;
+ case PROTOCOL_VERSION_9:
+ return V9;
default:
throw new IllegalArgumentException("Unrecognized protocol version " + protocolVersion);
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/AccountInfo.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/AccountInfo.java
index 23cb0f8bd..14cb07aa4 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/AccountInfo.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/AccountInfo.java
@@ -38,7 +38,7 @@ public final class AccountInfo {
*/
private final CCDAmount accountAmount;
/**
- * The available (unencrypted) balance of the account (i.e. that can be transferred
+ * The available (unencrypted) balance of CCD's of the account (i.e. that can be transferred
* or used to pay for transactions). This is the balance ({@link AccountInfo#accountAmount})
* minus the locked amount.
* The locked amount is the maximum of the amount in the release schedule ({@link AccountInfo#accountReleaseSchedule})
@@ -98,6 +98,12 @@ public final class AccountInfo {
@Singular
private final ImmutableList cooldowns;
+ /**
+ * The protocol level tokens (PLT) held by the account.
+ */
+ @Singular
+ private final ImmutableList tokens;
+
public boolean isBaker() {
return !Objects.isNull(bakerInfo);
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/AccountTransactionDetails.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/AccountTransactionDetails.java
index c5003edcd..f4370541a 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/AccountTransactionDetails.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/AccountTransactionDetails.java
@@ -176,6 +176,12 @@ public class AccountTransactionDetails {
*/
private final EncryptedAmountsRemovedResult removedFromEncryptedBalance;
+ /**
+ * The result of the protocol level token update.
+ * Present if the transaction was a {@link TokenUpdate}.
+ */
+ private final TokenUpdateResult tokenUpdate;
+
public static AccountTransactionDetails from(com.concordium.grpc.v2.AccountTransactionDetails tx) {
val sender = AccountAddress.from(tx.getSender());
val detailsBuilder = AccountTransactionDetails.builder().sender(sender).cost(CCDAmount.from(tx.getCost())).successful(true);
@@ -241,6 +247,9 @@ public static AccountTransactionDetails from(com.concordium.grpc.v2.AccountTrans
case DELEGATION_CONFIGURED:
detailsBuilder.type(TransactionResultEventType.DELEGATION_CONFIGURED).delegatorConfigured(DelegatorConfigured.from(effects.getDelegationConfigured(), sender));
break;
+ case TOKEN_UPDATE_EFFECT:
+ detailsBuilder.type(TransactionResultEventType.TOKEN_UPDATE_EFFECT).tokenUpdate(TokenUpdateResult.builder().effect(effects.getTokenUpdateEffect()).build());
+ break;
case EFFECT_NOT_SET:
throw new IllegalArgumentException("Unrecognized effect.");
}
@@ -415,6 +424,16 @@ private static void extractRejectReasonError(AccountTransactionDetailsBuilder de
case POOL_CLOSED:
detailsBuilder.rejectReason(new RejectReasonPoolClosed());
break;
+ case NON_EXISTENT_TOKEN_ID:
+ detailsBuilder.rejectReason(RejectReasonNotExistentTokenId.builder()
+ .tokenId(reason.getNonExistentTokenId())
+ .build());
+ break;
+ case TOKEN_UPDATE_TRANSACTION_FAILED:
+ detailsBuilder.rejectReason(RejectReasonTokenUpdateTransactionFailed.builder()
+ .tokenModuleRejectReason(reason.getTokenUpdateTransactionFailed())
+ .build());
+ break;
case REASON_NOT_SET:
break;
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/ChainUpdateDetails.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/ChainUpdateDetails.java
index beeedc654..aba51fa72 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/ChainUpdateDetails.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/ChainUpdateDetails.java
@@ -11,15 +11,12 @@
import com.concordium.sdk.transactions.CCDAmount;
import com.concordium.sdk.types.AccountAddress;
import com.concordium.sdk.types.Timestamp;
-import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.*;
import java.time.Duration;
-import java.util.Optional;
/**
- * Details of the different chain updates that
- * may occur on the chain.
+ * Details of a successful chain update.
*/
@EqualsAndHashCode(doNotUseGetters = true)
@Builder
@@ -157,6 +154,12 @@ public class ChainUpdateDetails {
*/
private final FinalizationCommitteeParameters finalizationCommitteeParametersUpdate;
+ /**
+ * Parameters that govern validator suspension were changed.
+ * This is only non-null if the type is {@link UpdateType#VALIDATOR_SCORE_PARAMETERS}
+ */
+ private final ValidatorScoreParameters validatorScoreParametersUpdate;
+
public static ChainUpdateDetails from(UpdateDetails update) {
val chainUpdateDetailsBuilder = ChainUpdateDetails
.builder()
@@ -272,6 +275,13 @@ public static ChainUpdateDetails from(UpdateDetails update) {
.type(UpdateType.UPDATE_FINALIZATION_COMMITTEE_PARAMETERS)
.finalizationCommitteeParametersUpdate(FinalizationCommitteeParameters.from(payload.getFinalizationCommitteeParametersUpdate()));
break;
+ case VALIDATOR_SCORE_PARAMETERS_UPDATE:
+ chainUpdateDetailsBuilder
+ .type(UpdateType.VALIDATOR_SCORE_PARAMETERS)
+ .validatorScoreParametersUpdate(ValidatorScoreParameters.from(payload.getValidatorScoreParametersUpdate()));
+ break;
+ case CREATE_PLT_UPDATE:
+ throw new IllegalStateException("This can't happen. CreatePLT operations are not enqueued, but happen immediately");
case PAYLOAD_NOT_SET:
throw new IllegalArgumentException("Unrecognized chain update");
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Details.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Details.java
index 5a7e1b1b1..8d599027d 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Details.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Details.java
@@ -1,6 +1,7 @@
package com.concordium.sdk.responses.blockitemsummary;
import com.concordium.grpc.v2.UpdateDetails;
+import com.concordium.grpc.v2.plt.TokenCreationDetails;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -37,6 +38,12 @@ public class Details {
*/
private final ChainUpdateDetails chainUpdateDetails;
+ /**
+ * Protocol-level token (PLT) creation details.
+ * This is only present if the type is {@link Type#TOKEN_CREATION}
+ */
+ private final TokenCreationDetails tokenCreationDetails;
+
public static Details newAccountTransaction(com.concordium.grpc.v2.AccountTransactionDetails accountTransaction) {
return Details.builder().type(Type.ACCOUNT_TRANSACTION).accountTransactionDetails(AccountTransactionDetails.from(accountTransaction)).build();
}
@@ -48,4 +55,8 @@ public static Details newAcountCreation(com.concordium.grpc.v2.AccountCreationDe
public static Details newChainUpdate(UpdateDetails update) {
return Details.builder().type(Type.CHAIN_UPDATE).chainUpdateDetails(ChainUpdateDetails.from(update)).build();
}
+
+ public static Details newTokenCreation(TokenCreationDetails tokenCreationDetails) {
+ return Details.builder().type(Type.TOKEN_CREATION).tokenCreationDetails(tokenCreationDetails).build();
+ }
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Summary.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Summary.java
index 3d81fb684..bfb34eddd 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Summary.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Summary.java
@@ -52,6 +52,9 @@ public static Summary from(BlockItemSummaryInBlock summary) {
case UPDATE:
builder.details(Details.newChainUpdate(outcome.getUpdate()));
break;
+ case TOKEN_CREATION:
+ builder.details(Details.newTokenCreation(outcome.getTokenCreation()));
+ break;
case DETAILS_NOT_SET:
throw new IllegalArgumentException("Details type is not set.");
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Type.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Type.java
index 5069a0ae6..b8cbc4137 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Type.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/Type.java
@@ -16,5 +16,9 @@ public enum Type {
/**
* A chain update
*/
- CHAIN_UPDATE
+ CHAIN_UPDATE,
+ /**
+ * A new protocol-level token (PLT) was created.
+ */
+ TOKEN_CREATION,
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/UpdateType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/UpdateType.java
index fd2466cee..33ec1d5b8 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/UpdateType.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/blockitemsummary/UpdateType.java
@@ -132,5 +132,11 @@ public enum UpdateType {
* of the finalization committee.
* This parameter is only applicable from protocol version 6 and onwards.
*/
- UPDATE_FINALIZATION_COMMITTEE_PARAMETERS
+ UPDATE_FINALIZATION_COMMITTEE_PARAMETERS,
+ /**
+ * Update to the {@link com.concordium.sdk.responses.chainparameters.ValidatorScoreParameters},
+ * parameters that govern validator suspension.
+ * This parameter is only applicable from protocol version 8 and onwards.
+ */
+ VALIDATOR_SCORE_PARAMETERS,
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/chainparameters/AuthorizationsV1.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/chainparameters/AuthorizationsV1.java
index 71b935159..869c28fdb 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/chainparameters/AuthorizationsV1.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/chainparameters/AuthorizationsV1.java
@@ -30,6 +30,12 @@ public class AuthorizationsV1 extends AuthorizationsV0 implements Authorizations
*/
private final AccessStructure timeParameters;
+ /**
+ * Keys allowed to create a protocol level token.
+ * This is present from protocol version 9.
+ */
+ private final AccessStructure createPltUpdate;
+
public static AuthorizationsV1 from(com.concordium.grpc.v2.AuthorizationsV1 value) {
val v0Authorizations = value.getV0();
val keys = v0Authorizations.getKeysList().stream().map(UpdatePublicKey::getValue).map(ByteString::toByteArray).map(ED25519PublicKey::from).collect(Collectors.toSet());
@@ -50,6 +56,11 @@ public static AuthorizationsV1 from(com.concordium.grpc.v2.AuthorizationsV1 valu
.keys(keys)
.timeParameters(AccessStructure.from(value.getParameterTime()))
.cooldownParameters(AccessStructure.from(value.getParameterCooldown()))
+ .createPltUpdate(
+ (value.hasCreatePlt())
+ ? AccessStructure.from(value.getCreatePlt())
+ : null
+ )
.build();
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonNotExistentTokenId.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonNotExistentTokenId.java
new file mode 100644
index 000000000..f9c0c53ea
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonNotExistentTokenId.java
@@ -0,0 +1,22 @@
+package com.concordium.sdk.responses.transactionstatus;
+
+import com.concordium.grpc.v2.plt.TokenId;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * The provided identifier does not match a token currently on chain.
+ * Introduced in protocol version 9.
+ */
+@ToString
+@Getter
+@Builder
+public class RejectReasonNotExistentTokenId extends RejectReason {
+ private final TokenId tokenId;
+
+ @Override
+ public RejectReasonType getType() {
+ return RejectReasonType.NOT_EXISTENT_TOKEN_ID;
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonTokenUpdateTransactionFailed.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonTokenUpdateTransactionFailed.java
new file mode 100644
index 000000000..3333a6560
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonTokenUpdateTransactionFailed.java
@@ -0,0 +1,22 @@
+package com.concordium.sdk.responses.transactionstatus;
+
+import com.concordium.grpc.v2.plt.TokenModuleRejectReason;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * The token update transaction failed.
+ * Introduced in protocol version 9.
+ */
+@ToString
+@Getter
+@Builder
+public class RejectReasonTokenUpdateTransactionFailed extends RejectReason {
+ private final TokenModuleRejectReason tokenModuleRejectReason;
+
+ @Override
+ public RejectReasonType getType() {
+ return RejectReasonType.TOKEN_UPDATE_TRANSACTION_FAILED;
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonType.java
index 977c6432b..94572a1c9 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonType.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/RejectReasonType.java
@@ -58,7 +58,10 @@ public enum RejectReasonType {
DELEGATION_TARGET_NOT_A_BAKER,
STAKE_OVER_MAXIMUM_THRESHOLD_FOR_POOL,
POOL_WOULD_BECOME_OVER_DELEGATED,
- POOL_CLOSED;
+ POOL_CLOSED,
+ NOT_EXISTENT_TOKEN_ID,
+ TOKEN_UPDATE_TRANSACTION_FAILED,
+ ;
public static RejectReasonType from(com.concordium.grpc.v2.RejectReason reason) {
switch (reason.getReasonCase()) {
@@ -170,6 +173,10 @@ public static RejectReasonType from(com.concordium.grpc.v2.RejectReason reason)
return POOL_WOULD_BECOME_OVER_DELEGATED;
case POOL_CLOSED:
return POOL_CLOSED;
+ case NON_EXISTENT_TOKEN_ID:
+ return NOT_EXISTENT_TOKEN_ID;
+ case TOKEN_UPDATE_TRANSACTION_FAILED:
+ return TOKEN_UPDATE_TRANSACTION_FAILED;
case REASON_NOT_SET:
throw new IllegalArgumentException("No reject reason present.");
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TokenUpdateResult.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TokenUpdateResult.java
new file mode 100644
index 000000000..658309ccd
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TokenUpdateResult.java
@@ -0,0 +1,16 @@
+package com.concordium.sdk.responses.transactionstatus;
+
+import com.concordium.grpc.v2.plt.TokenEffect;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public final class TokenUpdateResult implements TransactionResultEvent {
+ private final TokenEffect effect;
+
+ @Override
+ public TransactionResultEventType getType() {
+ return TransactionResultEventType.TOKEN_UPDATE_EFFECT;
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TransactionResultEventType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TransactionResultEventType.java
index 9cc98ad97..a4b644f6a 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TransactionResultEventType.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/TransactionResultEventType.java
@@ -93,6 +93,8 @@ public enum TransactionResultEventType {
BAKER_CONFIGURED,
@JsonProperty("DelegationConfigured")
DELEGATION_CONFIGURED,
+ @JsonProperty("TokenUpdateEffect")
+ TOKEN_UPDATE_EFFECT,
// An event that occurs when an account send an
// encrypted transfer.
// The result of such a transaction is a 'NEW_ENCRYPTED_AMOUNT' event for the
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/serializing/CborMapper.java b/concordium-sdk/src/main/java/com/concordium/sdk/serializing/CborMapper.java
new file mode 100644
index 000000000..d310f6d0a
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/serializing/CborMapper.java
@@ -0,0 +1,40 @@
+package com.concordium.sdk.serializing;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
+import com.fasterxml.jackson.dataformat.cbor.databind.CBORMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import lombok.val;
+
+import java.io.IOException;
+
+public class CborMapper {
+ public static ObjectMapper INSTANCE = new CBORMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ // Needed to deserialize Optional Fields
+ .registerModule(new Jdk8Module());
+
+ /**
+ * Writes given data as a value content.
+ * Using just writeBytes() for this purpose breaks array/object element counter in the generator.
+ * This method uses reflection.
+ */
+ public static void writeBytesAsValue(CBORGenerator generator,
+ byte[] data,
+ int offset,
+ int len) throws IOException {
+ try {
+ val verifyValueWrite = CBORGenerator.class.getDeclaredMethod("_verifyValueWrite", String.class);
+ verifyValueWrite.setAccessible(true);
+ verifyValueWrite.invoke(generator, "write bytes as value");
+ verifyValueWrite.setAccessible(false);
+ } catch (Exception e) {
+ throw new RuntimeException("Can't verify value write with reflection: " + e.getMessage(), e);
+ }
+
+ generator.writeBytes(data, offset, len);
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdate.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdate.java
new file mode 100644
index 000000000..edc364c4c
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdate.java
@@ -0,0 +1,68 @@
+package com.concordium.sdk.transactions;
+
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.concordium.sdk.transactions.tokens.TokenOperation;
+import com.concordium.sdk.types.UInt32;
+import com.concordium.sdk.types.UInt64;
+import lombok.*;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * A protocol-level token (PLT) transaction payload
+ * containing the actual operations.
+ */
+@ToString
+@Builder
+@Getter
+@EqualsAndHashCode(callSuper = true)
+public class TokenUpdate extends Payload {
+
+ /**
+ * Symbol (ID) of the token to execute operations on.
+ */
+ private final String tokenSymbol;
+
+ /**
+ * Operations to execute.
+ */
+ @Singular
+ private final List operations;
+
+ @Override
+ public TransactionType getTransactionType() {
+ return TransactionType.TOKEN_UPDATE;
+ }
+
+ @Override
+ @SneakyThrows
+ protected byte[] getRawPayloadBytes() {
+ val symbolBytes = tokenSymbol.getBytes(StandardCharsets.UTF_8);
+ val operationsBytes = CborMapper
+ .INSTANCE
+ .writeValueAsBytes(operations);
+
+ val buffer = ByteBuffer.allocate(
+ Byte.BYTES + symbolBytes.length
+ + UInt32.BYTES + operationsBytes.length
+ );
+
+ buffer.put((byte) symbolBytes.length);
+ buffer.put(symbolBytes);
+ buffer.putInt(operationsBytes.length);
+ buffer.put(operationsBytes);
+
+ return buffer.array();
+ }
+
+ public UInt64 getOperationsBaseCost() {
+ var total = UInt64.from(0L);
+ for (TokenOperation operation : operations) {
+ total = total.plus(operation.getBaseCost());
+ }
+ return total;
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdateTransaction.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdateTransaction.java
new file mode 100644
index 000000000..fa4ad22a8
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TokenUpdateTransaction.java
@@ -0,0 +1,59 @@
+package com.concordium.sdk.transactions;
+
+import com.concordium.sdk.exceptions.TransactionCreationException;
+import com.concordium.sdk.types.AccountAddress;
+import com.concordium.sdk.types.Nonce;
+import lombok.*;
+
+/**
+ * A protocol-level token (PLT) transaction.
+ * It is used to execute operations on a single PLT,
+ * such as transferring, minting, etc.
+ */
+@Getter
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TokenUpdateTransaction extends AccountTransaction {
+
+ private TokenUpdateTransaction(
+ @NonNull final TokenUpdate payload,
+ @NonNull final AccountAddress sender,
+ @NonNull final Nonce nonce,
+ @NonNull final Expiry expiry,
+ @NonNull final TransactionSigner signer) {
+ super(
+ sender,
+ nonce,
+ expiry,
+ signer,
+ payload,
+ TransactionTypeCost.TOKEN_UPDATE_BASE_COST.getValue()
+ .plus(payload.getOperationsBaseCost())
+ );
+ }
+
+ /**
+ * Creates new {@link TokenUpdateTransaction}.
+ *
+ * @param payload Payload for this Transaction.
+ * @param sender Sender ({@link AccountAddress}) of this Transaction.
+ * @param nonce Nonce {@link Nonce} Of the Sender Account.
+ * @param expiry {@link Expiry} of this transaction.
+ * @param signer {@link Signer} of this transaction.
+ * @return Initialized {@link TokenUpdateTransaction}
+ * @throws TransactionCreationException On failure to create the Transaction from input params.
+ * Ex when any of the input param is NULL.
+ */
+ @Builder
+ public static TokenUpdateTransaction from(final TokenUpdate payload,
+ final AccountAddress sender,
+ final Nonce nonce,
+ final Expiry expiry,
+ final TransactionSigner signer) {
+ try {
+ return new TokenUpdateTransaction(payload, sender, nonce, expiry, signer);
+ } catch (NullPointerException nullPointerException) {
+ throw TransactionCreationException.from(nullPointerException);
+ }
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionFactory.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionFactory.java
index 606520ef5..1cfaf7dc8 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionFactory.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionFactory.java
@@ -215,4 +215,15 @@ public static ConfigureBakerTransaction.ConfigureBakerTransactionBuilder newUpda
public static ConfigureDelegationTransaction.ConfigureDelegationTransactionBuilder newConfigureDelegation() {
return ConfigureDelegationTransaction.builder();
}
+
+ /**
+ * Creates a new {@link TokenUpdateTransaction.TokenUpdateTransactionBuilder} for creating a
+ * {@link TokenUpdateTransaction} to execute protocol-level token (PLT) operations
+ * such as transferring, minting, etc.
+ *
+ * @return the builder for a {@link TokenUpdateTransaction}
+ */
+ public static TokenUpdateTransaction.TokenUpdateTransactionBuilder newTokenUpdate() {
+ return TokenUpdateTransaction.builder();
+ }
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionType.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionType.java
index fa8c99e58..446e441a4 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionType.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionType.java
@@ -5,7 +5,6 @@
/**
* Type of Account Transaction.
*/
-// Types must match https://github.com/Concordium/concordium-base/blob/main/haskell-src/Concordium/Types/Execution.hs
public enum TransactionType {
DEPLOY_MODULE((byte) 0),
INITIALIZE_SMART_CONTRACT_INSTANCE((byte) 1),
@@ -27,7 +26,9 @@ public enum TransactionType {
ENCRYPTED_TRANSFER_WITH_MEMO((byte) 23),
TRANSFER_WITH_SCHEDULE_AND_MEMO((byte) 24),
CONFIGURE_BAKER((byte) 25),
- CONFIGURE_DELEGATION((byte) 26);
+ CONFIGURE_DELEGATION((byte) 26),
+ TOKEN_UPDATE((byte) 27),
+ ;
/**
* Number of Bytes used for Serializing {@link TransactionType}.
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionTypeCost.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionTypeCost.java
index 2657af300..79eff7ace 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionTypeCost.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/TransactionTypeCost.java
@@ -54,7 +54,14 @@ public enum TransactionTypeCost {
/**
* Base cost for a basic transfer.
*/
- TRANSFER_BASE_COST(300);
+ TRANSFER_BASE_COST(300),
+
+ /**
+ * Base cost for a token update transaction.
+ */
+ TOKEN_UPDATE_BASE_COST(300),
+ ;
+
/**
* The cost of the transaction
*/
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/CborMemo.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/CborMemo.java
new file mode 100644
index 000000000..387d4e7ab
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/CborMemo.java
@@ -0,0 +1,57 @@
+package com.concordium.sdk.transactions.tokens;
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
+import lombok.Getter;
+import lombok.SneakyThrows;
+import lombok.val;
+
+import java.io.IOException;
+
+@Getter
+@JsonSerialize(using = CborMemo.CborSerializer.class)
+public class CborMemo {
+
+ /**
+ * Memo content to be CBOR-encoded (Jackson), up to 256 bytes total.
+ */
+ private final byte[] content;
+
+ private CborMemo(byte[] content) {
+ if (content.length > 256) {
+ throw new IllegalArgumentException("The content can't exceed 256 bytes");
+ }
+ this.content = content;
+ }
+
+ /**
+ * @param content which is already CBOR-encoded, up to 256 bytes.
+ */
+ public static CborMemo from(byte[] content) {
+ return new CborMemo(content);
+ }
+
+ /**
+ * @param content to be CBOR-encoded (Jackson), up to 256 bytes total.
+ */
+ @SneakyThrows
+ public static CborMemo from(Object content) {
+ return new CborMemo(CborMapper.INSTANCE.writeValueAsBytes(content));
+ }
+
+ static class CborSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(CborMemo cborMemo,
+ JsonGenerator jsonGenerator,
+ SerializerProvider serializerProvider) throws IOException {
+ val cborGenerator = (CBORGenerator) jsonGenerator;
+ cborGenerator.writeTag(24);
+ cborGenerator.writeObject(cborMemo.content);
+ }
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TaggedTokenHolderAccount.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TaggedTokenHolderAccount.java
new file mode 100644
index 000000000..6231757aa
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TaggedTokenHolderAccount.java
@@ -0,0 +1,38 @@
+package com.concordium.sdk.transactions.tokens;
+
+import com.concordium.sdk.types.AccountAddress;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
+import lombok.Getter;
+import lombok.val;
+
+import java.io.IOException;
+
+@Getter
+@JsonSerialize(using = TaggedTokenHolderAccount.CborSerializer.class)
+public class TaggedTokenHolderAccount {
+
+ private final byte[] data;
+
+ public TaggedTokenHolderAccount(AccountAddress accountAddress) {
+ this.data = accountAddress.getBytes();
+ }
+
+ static class CborSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(TaggedTokenHolderAccount taggedTokenHolderAccount,
+ JsonGenerator jsonGenerator,
+ SerializerProvider serializerProvider) throws IOException {
+ val cborGenerator = (CBORGenerator) jsonGenerator;
+ cborGenerator.writeTag(40307);
+ cborGenerator.writeStartObject(taggedTokenHolderAccount, 1);
+ cborGenerator.writeFieldId(3);
+ cborGenerator.writeObject(taggedTokenHolderAccount.data);
+ cborGenerator.writeEndObject();
+ }
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperation.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperation.java
new file mode 100644
index 000000000..3df799625
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperation.java
@@ -0,0 +1,48 @@
+package com.concordium.sdk.transactions.tokens;
+
+import com.concordium.sdk.transactions.TokenUpdate;
+import com.concordium.sdk.types.UInt64;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
+import lombok.val;
+
+import java.io.IOException;
+
+/**
+ * A protocol-level token (PLT) operation used in {@link TokenUpdate}.
+ */
+@JsonSerialize(using = TokenOperation.CborSerializer.class)
+public interface TokenOperation {
+
+ /**
+ * @return operation type name, e.g. "transfer", "mint", etc.
+ */
+ String getType();
+
+ /**
+ * @return A CBOR-serializable (Jackson) operation body.
+ */
+ Object getBody();
+
+ /**
+ * @return the base energy cost of this operation.
+ */
+ UInt64 getBaseCost();
+
+ class CborSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(TokenOperation tokenOperation,
+ JsonGenerator jsonGenerator,
+ SerializerProvider serializerProvider) throws IOException {
+ val cborGenerator = (CBORGenerator) jsonGenerator;
+ cborGenerator.writeStartObject(tokenOperation, 1);
+ cborGenerator.writeFieldName(tokenOperation.getType());
+ cborGenerator.writeObject(tokenOperation.getBody());
+ cborGenerator.writeEndObject();
+ }
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperationAmount.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperationAmount.java
new file mode 100644
index 000000000..fb40e2eed
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TokenOperationAmount.java
@@ -0,0 +1,88 @@
+package com.concordium.sdk.transactions.tokens;
+
+import com.concordium.grpc.v2.plt.TokenAmount;
+import com.concordium.sdk.types.UInt64;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
+import lombok.Getter;
+import lombok.val;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+
+/**
+ * An amount for a protocol-level token (PLT) operation.
+ * It is very important for decimals to match the actual value of the token.
+ */
+@Getter
+@JsonSerialize(using = TokenOperationAmount.CborSerializer.class)
+public class TokenOperationAmount {
+
+ /**
+ * The integer amount.
+ * For example, "1.5" for a token with 6 decimals is "1500000".
+ */
+ private final UInt64 value;
+
+ /**
+ * The number of token decimals.
+ * It is very important for this value to match the actual value of the token.
+ */
+ private final int decimals;
+
+ public TokenOperationAmount(UInt64 value,
+ int decimals) {
+ this.value = value;
+
+ if (decimals < 0) {
+ throw new IllegalArgumentException("The number of decimals can't be negative");
+ } else if (decimals > 255) {
+ throw new IllegalArgumentException("The number of decimals can't exceed 255");
+ }
+
+ this.decimals = decimals;
+ }
+
+ public TokenOperationAmount(BigDecimal decimalValue,
+ int decimals) {
+ this(
+ new UInt64(
+ decimalValue
+ .movePointRight(decimals)
+ .toBigInteger()
+ ),
+ decimals
+ );
+ }
+
+ public TokenOperationAmount(TokenAmount tokenAmount) {
+ this(
+ UInt64.from(tokenAmount.getValue()),
+ tokenAmount.getDecimals()
+ );
+ }
+
+ static class CborSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(TokenOperationAmount tokenOperationAmount,
+ JsonGenerator jsonGenerator,
+ SerializerProvider serializerProvider) throws IOException {
+ val cborGenerator = (CBORGenerator) jsonGenerator;
+
+ // Write the amount as CBOR "decfrac" (decimal fraction),
+ // with the exponent matching the token decimals.
+ // For token module with 6 decimals,
+ // "1.5" must be encoded as 4([-6, 1500000]) and not as 4([-1, 15])
+ // even though the latter is shorter.
+ cborGenerator.writeTag(4);
+ cborGenerator.writeObject(new Object[]{
+ -tokenOperationAmount.decimals,
+ tokenOperationAmount.value
+ });
+ }
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TransferTokenOperation.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TransferTokenOperation.java
new file mode 100644
index 000000000..f9ee58ba5
--- /dev/null
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/TransferTokenOperation.java
@@ -0,0 +1,54 @@
+package com.concordium.sdk.transactions.tokens;
+
+import com.concordium.sdk.types.UInt64;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.val;
+
+import java.util.HashMap;
+import java.util.Optional;
+
+@Getter
+@Builder
+public class TransferTokenOperation implements TokenOperation {
+
+ /**
+ * Amount to be transferred.
+ * It very important that the decimals in it match the actual value of the token.
+ */
+ private final TokenOperationAmount amount;
+
+ /**
+ * Recipient of the transfer.
+ */
+ private final TaggedTokenHolderAccount recipient;
+
+ /**
+ * Optional memo (message) to be included to the transfer,
+ * which will be publicly available on the blockchain.
+ */
+ private final CborMemo memo;
+
+ public Optional getMemo() {
+ return Optional.ofNullable(memo);
+ }
+
+ @Override
+ public String getType() {
+ return "transfer";
+ }
+
+ @Override
+ public UInt64 getBaseCost() {
+ return UInt64.from(100);
+ }
+
+ @Override
+ public Object getBody() {
+ val body = new HashMap();
+ body.put("amount", amount);
+ body.put("recipient", recipient);
+ body.put("memo", memo);
+ return body;
+ }
+}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt32.java b/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt32.java
index e464f7a4b..95ba3252a 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt32.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt32.java
@@ -1,10 +1,11 @@
package com.concordium.sdk.types;
+import com.concordium.sdk.serializing.CborMapper;
import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.val;
@@ -66,25 +67,34 @@ public int compareTo(UInt32 other) {
return Integer.compareUnsigned(this.value, other.value);
}
+ public UInt32 plus(UInt32 other) {
+ return UInt32.from(this.value + other.value);
+ }
+
/**
* A custom Jackson serializer is provided that ensures that the unsigned value
* is the one used when serializing to JSON.
*/
- static class UInt32Serializer extends StdSerializer {
+ static class UInt32Serializer extends JsonSerializer {
- public UInt32Serializer() {
- this(null);
- }
+ @Override
+ public void serialize(UInt32 uint,
+ JsonGenerator generator,
+ SerializerProvider provider) throws IOException {
+ if (generator instanceof CBORGenerator) {
+ val cborGenerator = (CBORGenerator) generator;
- public UInt32Serializer(Class t) {
- super(t);
- }
+ // Write as unsigned 4-byte integer.
+ val value = ByteBuffer.allocate(1 + Integer.BYTES)
+ .put((byte) 0x1A)
+ .put(uint.getBytes())
+ .array();
+ CborMapper.writeBytesAsValue(cborGenerator, value, 0, value.length);
- @Override
- public void serialize(
- UInt32 uint, JsonGenerator jgen, SerializerProvider provider)
- throws IOException, JsonProcessingException {
- jgen.writeRawValue(Integer.toUnsignedString(uint.getValue()));
+ return;
+ }
+
+ generator.writeRawValue(Integer.toUnsignedString(uint.getValue()));
}
}
}
diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt64.java b/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt64.java
index 96ef3da90..6997e1168 100644
--- a/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt64.java
+++ b/concordium-sdk/src/main/java/com/concordium/sdk/types/UInt64.java
@@ -1,12 +1,12 @@
package com.concordium.sdk.types;
+import com.concordium.sdk.serializing.CborMapper;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
+import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.val;
@@ -74,25 +74,35 @@ public int compareTo(UInt64 other) {
return Long.compareUnsigned(this.value, other.value);
}
+ public UInt64 plus(UInt64 other) {
+ return UInt64.from(this.value + other.value);
+ }
+
/**
* A custom Jackson serializer is provided that ensures that the unsigned value
* is the one used when serializing to JSON.
*/
- static class UInt64Serializer extends StdSerializer {
+ static class UInt64Serializer extends JsonSerializer {
- public UInt64Serializer() {
- this(null);
- }
+ @Override
+ public void serialize(UInt64 uint,
+ JsonGenerator generator,
+ SerializerProvider provider) throws IOException {
- public UInt64Serializer(Class t) {
- super(t);
- }
+ if (generator instanceof CBORGenerator) {
+ val cborGenerator = (CBORGenerator) generator;
- @Override
- public void serialize(
- UInt64 uint, JsonGenerator jgen, SerializerProvider provider)
- throws IOException, JsonProcessingException {
- jgen.writeRawValue(Long.toUnsignedString(uint.getValue()));
+ // Write as unsigned 8-byte integer.
+ val value = ByteBuffer.allocate(1 + Long.BYTES)
+ .put((byte) 0x1B)
+ .put(uint.getBytes())
+ .array();
+ CborMapper.writeBytesAsValue(cborGenerator, value, 0, value.length);
+
+ return;
+ }
+
+ generator.writeRawValue(Long.toUnsignedString(uint.getValue()));
}
}
}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/tokens/CborMemoTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/CborMemoTest.java
new file mode 100644
index 000000000..c38875a35
--- /dev/null
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/CborMemoTest.java
@@ -0,0 +1,68 @@
+package com.concordium.sdk.tokens;
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.concordium.sdk.transactions.tokens.CborMemo;
+import lombok.SneakyThrows;
+import org.bouncycastle.util.encoders.Hex;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.security.SecureRandom;
+
+public class CborMemoTest {
+
+ @SneakyThrows
+ @Test
+ public void testCborMemoStringSerialization() {
+ Assert.assertEquals(
+ "d8184c6b48656c6c6f20776f726c64",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ CborMemo.from("Hello world")
+ )
+ )
+ );
+ Assert.assertEquals(
+ "d818584f784dd09dd0b5d0bfd0bbd0bed185d0be20d181d180d0b0d0b1d0bed182d0b0d0bdd0be2c20d0bcd0b8d181d182d0b5d18020d0a0d0b0d0b72dd094d0b2d0b020f09f91a9f09f8fbbe2808df09f94ac",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ CborMemo.from("Неплохо сработано, мистер Раз-Два 👩🏻🔬")
+ )
+ )
+ );
+ }
+
+ @SneakyThrows
+ @Test
+ public void testCborMemoRawSerialization() {
+ Assert.assertEquals(
+ "d81843010203",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ CborMemo.from(new byte[]{1, 2, 3})
+ )
+ )
+ );
+ }
+
+ @SneakyThrows
+ @Test
+ public void testCborMemoNullSerialization() {
+ Assert.assertEquals(
+ "d81841f6",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ CborMemo.from((Object) null)
+ )
+ )
+ );
+ }
+
+ @SneakyThrows
+ @Test(
+ expected = IllegalArgumentException.class
+ )
+ public void testCborMemoTooBig() {
+ CborMemo.from(SecureRandom.getSeed(257));
+ }
+}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TaggedTokenHolderAccountTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TaggedTokenHolderAccountTest.java
new file mode 100644
index 000000000..8f9a410b6
--- /dev/null
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TaggedTokenHolderAccountTest.java
@@ -0,0 +1,29 @@
+package com.concordium.sdk.tokens;
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.concordium.sdk.transactions.tokens.TaggedTokenHolderAccount;
+import com.concordium.sdk.types.AccountAddress;
+import lombok.SneakyThrows;
+import org.bouncycastle.util.encoders.Hex;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TaggedTokenHolderAccountTest {
+
+ @Test
+ @SneakyThrows
+ public void testTaggedTokenHolderAccountSerialization() {
+ Assert.assertEquals(
+ "d99d73a10358201515151515151515151515151515151515151515151515151515151515151515",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TaggedTokenHolderAccount(
+ AccountAddress.from(
+ Hex.decode("1515151515151515151515151515151515151515151515151515151515151515")
+ )
+ )
+ )
+ )
+ );
+ }
+}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TokenOperationAmountTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TokenOperationAmountTest.java
new file mode 100644
index 000000000..21c0e75f1
--- /dev/null
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TokenOperationAmountTest.java
@@ -0,0 +1,72 @@
+package com.concordium.sdk.tokens;
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.concordium.sdk.transactions.tokens.TokenOperationAmount;
+import com.concordium.sdk.types.UInt64;
+import lombok.SneakyThrows;
+import org.bouncycastle.util.encoders.Hex;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TokenOperationAmountTest {
+
+ @Test
+ @SneakyThrows
+ public void testTokenOperationAmountSerialization() {
+ Assert.assertEquals(
+ "c482251b000000000016e360",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TokenOperationAmount(
+ UInt64.from("1500000"),
+ 6
+ )
+ )
+ )
+ );
+ Assert.assertEquals(
+ "c482221b000000000012d687",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TokenOperationAmount(
+ UInt64.from("1234567"),
+ 3
+ )
+ )
+ )
+ );
+ Assert.assertEquals(
+ "c482221b8000000000000000",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TokenOperationAmount(
+ UInt64.from(Long.MIN_VALUE),
+ 3
+ )
+ )
+ )
+ );
+ Assert.assertEquals(
+ "c482221b7fffffffffffffff",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TokenOperationAmount(
+ UInt64.from(Long.MAX_VALUE),
+ 3
+ )
+ )
+ )
+ );
+ Assert.assertEquals(
+ "c482221bffffffffffffffff",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ new TokenOperationAmount(
+ UInt64.from(-1),
+ 3
+ )
+ )
+ )
+ );
+ }
+}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TransferTokenOperationTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TransferTokenOperationTest.java
new file mode 100644
index 000000000..dfb35e3ab
--- /dev/null
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/TransferTokenOperationTest.java
@@ -0,0 +1,78 @@
+package com.concordium.sdk.tokens;
+
+import com.concordium.sdk.serializing.CborMapper;
+import com.concordium.sdk.transactions.tokens.CborMemo;
+import com.concordium.sdk.transactions.tokens.TaggedTokenHolderAccount;
+import com.concordium.sdk.transactions.tokens.TokenOperationAmount;
+import com.concordium.sdk.transactions.tokens.TransferTokenOperation;
+import com.concordium.sdk.types.AccountAddress;
+import com.concordium.sdk.types.UInt64;
+import lombok.SneakyThrows;
+import org.bouncycastle.util.encoders.Hex;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+public class TransferTokenOperationTest {
+
+ @Test
+ @SneakyThrows
+ public void testTokenTransferOperationSerialization() {
+ Assert.assertEquals(
+ "a1687472616e73666572bf66616d6f756e74c482251b000000000016e36069726563697069656e74d99d73a103582021bc8745c81c07ca7f3fb79a8bd161624cb1d5da788baec13f5a5d9eac3a29b7646d656d6fd81848674d79206d656d6fff",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ TransferTokenOperation
+ .builder()
+ .amount(new TokenOperationAmount(UInt64.from("1500000"), 6))
+ .memo(CborMemo.from("My memo"))
+ .recipient(new TaggedTokenHolderAccount(
+ AccountAddress.from(
+ "3CbvrNVpcHpL7tyT2mhXxQwNWHiPNYEJRgp3CMgEcMyXivms6B"
+ )
+ ))
+ .build()
+ )
+ )
+ );
+ }
+
+ @Test
+ @SneakyThrows
+ public void testTokenTransferOperationWithoutMemoSerialization() {
+ Assert.assertEquals(
+ "a1687472616e73666572bf66616d6f756e74c482251b000000000016e36069726563697069656e74d99d73a103582021bc8745c81c07ca7f3fb79a8bd161624cb1d5da788baec13f5a5d9eac3a29b7ff",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ TransferTokenOperation
+ .builder()
+ .amount(new TokenOperationAmount(new BigDecimal("1.5"), 6))
+ .recipient(new TaggedTokenHolderAccount(
+ AccountAddress.from(
+ "3CbvrNVpcHpL7tyT2mhXxQwNWHiPNYEJRgp3CMgEcMyXivms6B"
+ )
+ ))
+ .build()
+ )
+ )
+ );
+
+ Assert.assertEquals(
+ "a1687472616e73666572bf66616d6f756e74c482231b000000000000007b69726563697069656e74d99d73a10358201515151515151515151515151515151515151515151515151515151515151515ff",
+ Hex.toHexString(
+ CborMapper.INSTANCE.writeValueAsBytes(
+ TransferTokenOperation
+ .builder()
+ .amount(new TokenOperationAmount(UInt64.from("123"), 4))
+ .recipient(new TaggedTokenHolderAccount(
+ AccountAddress.from(
+ Hex.decode("1515151515151515151515151515151515151515151515151515151515151515")
+ )
+ ))
+ .build()
+ )
+ )
+ );
+ }
+}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTransactionTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTransactionTest.java
new file mode 100644
index 000000000..4eb66f8d1
--- /dev/null
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTransactionTest.java
@@ -0,0 +1,138 @@
+package com.concordium.sdk.transactions;
+
+import com.concordium.grpc.v2.plt.TokenId;
+import com.concordium.sdk.transactions.tokens.CborMemo;
+import com.concordium.sdk.transactions.tokens.TaggedTokenHolderAccount;
+import com.concordium.sdk.transactions.tokens.TokenOperationAmount;
+import com.concordium.sdk.transactions.tokens.TransferTokenOperation;
+import com.concordium.sdk.types.AccountAddress;
+import com.concordium.sdk.types.Nonce;
+import com.concordium.sdk.types.UInt64;
+import lombok.SneakyThrows;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+public class TokenUpdateTransactionTest {
+
+ @Test
+ @SneakyThrows
+ public void testTokenUpdateTransferTransactionWithTextMemo() {
+ Assert.assertEquals(
+ "24303123d37c83a071bf861bb5d4490f945e4253234890062d851fd75c4bf25c",
+ TransactionFactory
+ .newTokenUpdate()
+ .sender(AccountAddress.from("3JwD2Wm3nMbsowCwb1iGEpnt47UQgdrtnq2qT6opJc3z2AgCrc"))
+ .payload(
+ TokenUpdate
+ .builder()
+ .tokenSymbol("TEST")
+ .operation(
+ TransferTokenOperation
+ .builder()
+ .amount(
+ new TokenOperationAmount(
+ new BigDecimal("1.5"),
+ 2
+ )
+ )
+ .recipient(
+ new TaggedTokenHolderAccount(
+ AccountAddress.from("3hYXYEPuGyhFcVRhSk2cVgKBhzVcAryjPskYk4SecpwGnoHhuM")
+ )
+ )
+ .memo(
+ CborMemo.from("Memo for the test")
+ )
+ .build()
+ )
+ .build()
+ )
+ .nonce(Nonce.from(78910))
+ .expiry(Expiry.from(123456))
+ .signer(TransactionTestHelper.getValidSigner())
+ .build()
+ .getHash()
+ .asHex()
+ );
+ }
+
+ @Test
+ @SneakyThrows
+ public void testTokenUpdateTransferTransactionWithoutMemo() {
+ Assert.assertEquals(
+ "76d7e2c3f3e2046eb145783f7bda8c26c216e2f2db3a195f41ffb7640981077a",
+ TransactionFactory
+ .newTokenUpdate()
+ .sender(AccountAddress.from("3JwD2Wm3nMbsowCwb1iGEpnt47UQgdrtnq2qT6opJc3z2AgCrc"))
+ .payload(
+ TokenUpdate
+ .builder()
+ .tokenSymbol("TEST")
+ .operation(
+ TransferTokenOperation
+ .builder()
+ .amount(
+ new TokenOperationAmount(
+ new BigDecimal("1.5"),
+ 2
+ )
+ )
+ .recipient(
+ new TaggedTokenHolderAccount(
+ AccountAddress.from("3hYXYEPuGyhFcVRhSk2cVgKBhzVcAryjPskYk4SecpwGnoHhuM")
+ )
+ )
+ .build()
+ )
+ .build()
+ )
+ .nonce(Nonce.from(78910))
+ .expiry(Expiry.from(123456))
+ .signer(TransactionTestHelper.getValidSigner())
+ .build()
+ .getHash()
+ .asHex()
+ );
+ }
+
+ @Test
+ @SneakyThrows
+ public void testTokenUpdateTransferTransactionCostWithoutMemo() {
+ Assert.assertEquals(
+ UInt64.from("751"),
+ TransactionFactory
+ .newTokenUpdate()
+ .sender(AccountAddress.from("3JwD2Wm3nMbsowCwb1iGEpnt47UQgdrtnq2qT6opJc3z2AgCrc"))
+ .payload(
+ TokenUpdate
+ .builder()
+ .tokenSymbol("TEST")
+ .operation(
+ TransferTokenOperation
+ .builder()
+ .amount(
+ new TokenOperationAmount(
+ new BigDecimal("1.5"),
+ 2
+ )
+ )
+ .recipient(
+ new TaggedTokenHolderAccount(
+ AccountAddress.from("3hYXYEPuGyhFcVRhSk2cVgKBhzVcAryjPskYk4SecpwGnoHhuM")
+ )
+ )
+ .build()
+ )
+ .build()
+ )
+ .nonce(Nonce.from(78910))
+ .expiry(Expiry.from(123456))
+ .signer(TransactionTestHelper.getValidSigner())
+ .build()
+ .getHeader()
+ .getMaxEnergyCost()
+ );
+ }
+}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt32Test.java b/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt32Test.java
index 54e40e3bf..e22e51866 100644
--- a/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt32Test.java
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt32Test.java
@@ -31,12 +31,30 @@ public void testComparable() {
assertEquals(-1, UInt32.from("4294967294").compareTo(UInt32.from("4294967295")));
}
+ @Test
+ public void testAdding() {
+ assertEquals(
+ 5,
+ UInt32.from(3).plus(UInt32.from(2)).getValue()
+ );
+ // UInt32 max
+ assertEquals(
+ -1,
+ UInt32.from(Integer.MIN_VALUE).plus(UInt32.from(Integer.MAX_VALUE)).getValue()
+ );
+ // Overflow
+ assertEquals(
+ 0,
+ UInt32.from(Integer.MIN_VALUE).plus(UInt32.from(Integer.MIN_VALUE)).getValue()
+ );
+ }
+
@Test
public void testSerializeDeserialize() {
- val expected = UInt64.from("123242112");
+ val expected = UInt32.from("123242112");
val bytes = expected.getBytes();
- val deserialized = UInt64.from(bytes);
+ val deserialized = UInt32.from(bytes);
assertEquals(expected, deserialized);
- assertNotEquals(expected, UInt64.from("42"));
+ assertNotEquals(expected, UInt32.from("42"));
}
}
diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt64Test.java b/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt64Test.java
index fdc4a3462..480a5f283 100644
--- a/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt64Test.java
+++ b/concordium-sdk/src/test/java/com/concordium/sdk/types/UInt64Test.java
@@ -34,4 +34,21 @@ public void testSerializeDeserialize() {
assertEquals(expected, deserialized);
}
+ @Test
+ public void testAdding() {
+ assertEquals(
+ 5,
+ UInt64.from(3).plus(UInt64.from(2)).getValue()
+ );
+ // UInt64 max
+ assertEquals(
+ -1L,
+ UInt64.from(Long.MIN_VALUE).plus(UInt64.from(Long.MAX_VALUE)).getValue()
+ );
+ // Overflow
+ assertEquals(
+ 0,
+ UInt64.from(Long.MIN_VALUE).plus(UInt64.from(Long.MIN_VALUE)).getValue()
+ );
+ }
}
diff --git a/crypto-jni/Cargo.lock b/crypto-jni/Cargo.lock
index b102d247f..92bf96768 100644
--- a/crypto-jni/Cargo.lock
+++ b/crypto-jni/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "ahash"
@@ -79,7 +79,7 @@ dependencies = [
"ark-std",
"derivative",
"hashbrown 0.13.2",
- "itertools",
+ "itertools 0.10.5",
"num-traits",
"zeroize",
]
@@ -96,7 +96,7 @@ dependencies = [
"ark-std",
"derivative",
"digest",
- "itertools",
+ "itertools 0.10.5",
"num-bigint",
"num-traits",
"paste",
@@ -232,47 +232,25 @@ dependencies = [
[[package]]
name = "borsh"
-version = "0.9.3"
+version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa"
+checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
dependencies = [
"borsh-derive",
- "hashbrown 0.11.2",
+ "cfg_aliases",
]
[[package]]
name = "borsh-derive"
-version = "0.9.3"
+version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775"
+checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3"
dependencies = [
- "borsh-derive-internal",
- "borsh-schema-derive-internal",
+ "once_cell",
"proc-macro-crate",
- "proc-macro2",
- "syn 1.0.107",
-]
-
-[[package]]
-name = "borsh-derive-internal"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.107",
-]
-
-[[package]]
-name = "borsh-schema-derive-internal"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0"
-dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.107",
+ "syn 2.0.104",
]
[[package]]
@@ -293,19 +271,20 @@ checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytecheck"
-version = "0.6.9"
+version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f"
+checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
dependencies = [
"bytecheck_derive",
"ptr_meta",
+ "simdutf8",
]
[[package]]
name = "bytecheck_derive"
-version = "0.6.9"
+version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
+checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
dependencies = [
"proc-macro2",
"quote",
@@ -320,9 +299,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
-version = "1.3.0"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
@@ -342,6 +321,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
[[package]]
name = "chrono"
version = "0.4.35"
@@ -357,6 +342,22 @@ dependencies = [
"windows-targets",
]
+[[package]]
+name = "ciborium-io"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
+
+[[package]]
+name = "ciborium-ll"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
+dependencies = [
+ "ciborium-io",
+ "half",
+]
+
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@@ -394,7 +395,7 @@ dependencies = [
"rust_decimal",
"serde",
"serde_json",
- "thiserror",
+ "thiserror 1.0.38",
]
[[package]]
@@ -403,12 +404,12 @@ version = "4.1.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
name = "concordium_base"
-version = "6.0.0"
+version = "8.0.0-alpha.2"
dependencies = [
"anyhow",
"ark-bls12-381",
@@ -419,6 +420,8 @@ dependencies = [
"bs58",
"byteorder",
"chrono",
+ "ciborium-io",
+ "ciborium-ll",
"concordium-contracts-common",
"concordium_base_derive",
"curve25519-dalek",
@@ -427,7 +430,7 @@ dependencies = [
"either",
"ff 0.13.0",
"hex",
- "itertools",
+ "itertools 0.14.0",
"leb128",
"libc",
"nom",
@@ -443,17 +446,20 @@ dependencies = [
"sha2",
"sha3",
"subtle",
- "thiserror",
+ "thiserror 2.0.12",
"zeroize",
]
[[package]]
name = "concordium_base_derive"
-version = "1.0.0"
+version = "1.1.0-alpha.2"
dependencies = [
+ "convert_case 0.8.0",
+ "darling",
+ "proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -468,6 +474,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+[[package]]
+name = "convert_case"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
+dependencies = [
+ "unicode-segmentation",
+]
+
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@@ -526,6 +541,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "crunchy"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
+
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -599,7 +620,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -648,9 +669,9 @@ dependencies = [
[[package]]
name = "darling"
-version = "0.20.3"
+version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
+checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
@@ -658,27 +679,27 @@ dependencies = [
[[package]]
name = "darling_core"
-version = "0.20.3"
+version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
+checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
name = "darling_macro"
-version = "0.20.3"
+version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
+checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -717,7 +738,7 @@ version = "0.99.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
dependencies = [
- "convert_case",
+ "convert_case 0.4.0",
"proc-macro2",
"quote",
"rustc_version",
@@ -789,7 +810,7 @@ dependencies = [
"hmac",
"regex",
"sha2",
- "thiserror",
+ "thiserror 1.0.38",
]
[[package]]
@@ -881,14 +902,21 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "half"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
+dependencies = [
+ "cfg-if",
+ "crunchy",
+]
+
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
-dependencies = [
- "ahash 0.7.6",
-]
[[package]]
name = "hashbrown"
@@ -910,9 +938,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.14.0"
+version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "hermit-abi"
@@ -996,12 +1024,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.0.0"
+version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
- "hashbrown 0.14.0",
+ "hashbrown 0.15.4",
"serde",
]
@@ -1025,6 +1053,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "1.0.5"
@@ -1041,7 +1078,7 @@ dependencies = [
"combine",
"jni-sys",
"log",
- "thiserror",
+ "thiserror 1.0.38",
"walkdir",
]
@@ -1071,7 +1108,7 @@ dependencies = [
[[package]]
name = "key_derivation"
-version = "2.1.0"
+version = "2.1.1"
dependencies = [
"concordium_base",
"ed25519-dalek",
@@ -1081,7 +1118,7 @@ dependencies = [
"pbkdf2",
"serde",
"sha2",
- "thiserror",
+ "thiserror 1.0.38",
]
[[package]]
@@ -1267,9 +1304,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "password-hash"
-version = "0.3.2"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8"
+checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
dependencies = [
"base64ct",
"rand_core 0.6.4",
@@ -1284,9 +1321,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pbkdf2"
-version = "0.10.1"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7"
+checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"digest",
"hmac",
@@ -1324,7 +1361,7 @@ dependencies = [
"phf_shared",
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -1374,18 +1411,18 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
-version = "0.1.5"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
+checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
dependencies = [
- "toml",
+ "toml_edit",
]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
@@ -1412,9 +1449,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.32"
+version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
@@ -1500,7 +1537,7 @@ checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
"libredox",
- "thiserror",
+ "thiserror 1.0.38",
]
[[package]]
@@ -1534,32 +1571,36 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "rend"
-version = "0.3.6"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95"
+checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
dependencies = [
"bytecheck",
]
[[package]]
name = "rkyv"
-version = "0.7.39"
+version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15"
+checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
dependencies = [
+ "bitvec",
"bytecheck",
+ "bytes",
"hashbrown 0.12.3",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
+ "tinyvec",
+ "uuid",
]
[[package]]
name = "rkyv_derive"
-version = "0.7.39"
+version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
+checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
dependencies = [
"proc-macro2",
"quote",
@@ -1568,14 +1609,12 @@ dependencies = [
[[package]]
name = "rust_decimal"
-version = "1.28.0"
+version = "1.37.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8"
+checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d"
dependencies = [
"arrayvec",
"borsh",
- "bytecheck",
- "byteorder",
"bytes",
"num-traits",
"rand",
@@ -1667,7 +1706,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -1691,7 +1730,7 @@ dependencies = [
"chrono",
"hex",
"indexmap 1.9.3",
- "indexmap 2.0.0",
+ "indexmap 2.10.0",
"serde",
"serde_json",
"serde_with_macros",
@@ -1707,7 +1746,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
@@ -1740,6 +1779,12 @@ dependencies = [
"rand_core 0.6.4",
]
+[[package]]
+name = "simdutf8"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+
[[package]]
name = "siphasher"
version = "0.3.11"
@@ -1758,9 +1803,9 @@ dependencies = [
[[package]]
name = "strsim"
-version = "0.10.0"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
@@ -1781,9 +1826,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.32"
+version = "2.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
+checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
dependencies = [
"proc-macro2",
"quote",
@@ -1834,7 +1879,16 @@ version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.38",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+dependencies = [
+ "thiserror-impl 2.0.12",
]
[[package]]
@@ -1848,6 +1902,17 @@ dependencies = [
"syn 1.0.107",
]
+[[package]]
+name = "thiserror-impl"
+version = "2.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
[[package]]
name = "time"
version = "0.3.28"
@@ -1892,12 +1957,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
-name = "toml"
-version = "0.5.11"
+name = "toml_datetime"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
- "serde",
+ "indexmap 2.10.0",
+ "toml_datetime",
+ "winnow",
]
[[package]]
@@ -1912,6 +1985,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
[[package]]
name = "unicode-width"
version = "0.1.10"
@@ -1924,6 +2003,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+[[package]]
+name = "uuid"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
+
[[package]]
name = "version_check"
version = "0.9.4"
@@ -1955,7 +2040,7 @@ dependencies = [
"rust_iso3166",
"serde",
"serde_json",
- "thiserror",
+ "thiserror 1.0.38",
]
[[package]]
@@ -2115,6 +2200,15 @@ version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
+[[package]]
+name = "winnow"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "wyz"
version = "0.5.1"
@@ -2141,7 +2235,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.104",
]
[[package]]
diff --git a/pom.xml b/pom.xml
index c39696da8..a6bcb38a4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.concordium.sdk
concordium-sdk-base
- 11.0.0-SNAPSHOT
+ 11.0.0
pom
https://github.com/Concordium/concordium-java-sdk
@@ -35,6 +35,109 @@
concordium-sdk
concordium-android-sdk
- concordium-sdk-examples
+
+
+
+
+ org.bitcoinj
+ bitcoinj-core
+ 0.16.2
+
+
+ com.google.protobuf
+ protobuf-javalite
+
+
+
+
+ io.grpc
+ grpc-netty-shaded
+ 1.73.0
+
+
+ io.grpc
+ grpc-okhttp
+ 1.73.0
+
+
+ io.grpc
+ grpc-protobuf
+ 1.73.0
+
+
+ io.grpc
+ grpc-testing
+ 1.73.0
+ test
+
+
+ io.grpc
+ grpc-stub
+ 1.73.0
+
+
+ javax.annotation
+ javax.annotation-api
+ 1.2
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.26
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.19.1
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.19.1
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-cbor
+ 2.19.1
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.19.1
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+ 2.19.1
+
+
+ commons-codec
+ commons-codec
+ 1.18.0
+
+
+ commons-io
+ commons-io
+ 2.19.0
+
+
+ org.mockito
+ mockito-core
+ 3.3.3
+ test
+
+
+ org.apache.commons
+ commons-lang3
+ 3.17.0
+
+
+