From 44006dcf708784e1dc0a8c01f2d46498023dc92b Mon Sep 17 00:00:00 2001 From: rba Date: Fri, 20 Feb 2026 17:49:05 +0000 Subject: [PATCH 1/6] initial play around --- concordium-android-sdk/pom.xml | 2 +- concordium-sdk-examples/pom.xml | 2 +- .../concordium/sdk/examples/MintToken.java | 96 +++++++++++++++++++ concordium-sdk/pom.xml | 2 +- .../tokens/MintTokenOperation.java | 39 ++++++++ pom.xml | 2 +- 6 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java diff --git a/concordium-android-sdk/pom.xml b/concordium-android-sdk/pom.xml index 24351a1a9..d85fa6003 100644 --- a/concordium-android-sdk/pom.xml +++ b/concordium-android-sdk/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1 + 12.1.0-alpha.1-SNAPSHOT concordium-android-sdk diff --git a/concordium-sdk-examples/pom.xml b/concordium-sdk-examples/pom.xml index 52858e30e..e7ed42994 100644 --- a/concordium-sdk-examples/pom.xml +++ b/concordium-sdk-examples/pom.xml @@ -23,7 +23,7 @@ com.concordium.sdk concordium-sdk - 12.0.0 + 12.1.0-alpha.1-SNAPSHOT org.projectlombok diff --git a/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java new file mode 100644 index 000000000..f5785d128 --- /dev/null +++ b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java @@ -0,0 +1,96 @@ +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.MintTokenOperation; +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 = "MintToken", mixinStandardHelpOptions = true) +public class MintToken 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 = "TestTokenSDK"; + TokenOperationAmount amount = new TokenOperationAmount( + new BigDecimal("10"), + 10 + ); + + AccountAddress sender = AccountAddress.from("49jjCXb13jWeXjHmb4k5wLHz6VGzxmWijua5VV99keQCo2uMdU"); + Expiry expiry = Expiry.createNew().addMinutes(5); + + TransactionSigner signer = TransactionSigner.from( + SignerEntry.from(Index.from(0), Index.from(0), + ED25519SecretKey + .from("0ee537b1eb7108a54dce9e506c3316e500c1c9997d3e83c8245cdd5fc326290f"))); + + var client = ClientV2.from(connection); + var senderInfo = client.getAccountInfo(BlockQuery.BEST, AccountQuery.from(sender)); + var nonce = senderInfo.getNonce(); + var txnHash = client.sendTransaction( + TransactionFactory + .newTokenUpdate( TokenUpdate + .builder() + .tokenSymbol(tokenSymbol) + .operation( + MintTokenOperation + .builder() + .amount(amount) + .build() + ).build() + ) + .nonce(nonce) + .expiry(expiry) + .sender(sender) + .sign(signer) + ); + 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 MintToken()).execute(args); + System.exit(exitCode); + } +} diff --git a/concordium-sdk/pom.xml b/concordium-sdk/pom.xml index e41d807ec..50948b83f 100644 --- a/concordium-sdk/pom.xml +++ b/concordium-sdk/pom.xml @@ -7,7 +7,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1 + 12.1.0-alpha.1-SNAPSHOT concordium-sdk diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java new file mode 100644 index 000000000..aff87250e --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java @@ -0,0 +1,39 @@ +package com.concordium.sdk.transactions.tokens; + +import com.concordium.sdk.types.UInt64; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +import java.util.Optional; + +/** + * Mint Token + * @see CBOR Schema + */ +@Getter +@Builder +@EqualsAndHashCode +@ToString +// This is for CBOR serialization to use the generated builder. +@Jacksonized +public class MintTokenOperation implements TokenOperation { + + /** + * Amount to be transferred. + * It very important that the decimals in it match the actual value of the token. + */ + @NonNull + private final TokenOperationAmount amount; + + @Override + public UInt64 getBaseCost() { + return UInt64.from(100); + } + + @Override + public String getType() { + return TYPE; + } + + public static final String TYPE = "mint"; +} diff --git a/pom.xml b/pom.xml index 6909f722b..43b18a4be 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1 + 12.1.0-alpha.1-SNAPSHOT pom https://github.com/Concordium/concordium-java-sdk From 14cf4fe985d796e718ed620c4eabfb1cfc93f31b Mon Sep 17 00:00:00 2001 From: rba Date: Mon, 23 Feb 2026 10:54:52 +0000 Subject: [PATCH 2/6] adding Mint Token operation --- .../concordium/sdk/examples/MintToken.java | 19 +++++---- .../transactions/tokens/TokenOperation.java | 4 ++ .../sdk/tokens/MintTokenOperationTest.java | 37 ++++++++++++++++++ .../sdk/transactions/TokenUpdateTest.java | 39 +++++++++++++++++-- 4 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 concordium-sdk/src/test/java/com/concordium/sdk/tokens/MintTokenOperationTest.java diff --git a/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java index f5785d128..ada895734 100644 --- a/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java +++ b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/MintToken.java @@ -2,15 +2,12 @@ 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.MintTokenOperation; import com.concordium.sdk.types.AccountAddress; @@ -30,7 +27,7 @@ public class MintToken implements Callable { @Option( names = {"--endpoint"}, description = "GRPC interface of the node.", - defaultValue = "https://grpc.devnet-plt-beta.concordium.com:20000") + defaultValue = "https://127.0.0.1:7000") private String endpoint; @Option( @@ -46,22 +43,24 @@ public Integer call() throws MalformedURLException, ClientInitializationExceptio Connection connection = Connection.newBuilder() .host(endpointUrl.getHost()) .port(endpointUrl.getPort()) - .useTLS(TLSConfig.auto()) + //.useTLS(TLSConfig.auto()) //update this as necessary if using tls or not .build(); - String tokenSymbol = "TestTokenSDK"; + String tokenSymbol = "RRR10"; // Replace this with the appropriate token symbol in your node TokenOperationAmount amount = new TokenOperationAmount( - new BigDecimal("10"), - 10 + new BigDecimal("1"), + 6 //ensure the decimal precision here matches the value of the decimal during token creation ); - AccountAddress sender = AccountAddress.from("49jjCXb13jWeXjHmb4k5wLHz6VGzxmWijua5VV99keQCo2uMdU"); + //use an address valid in the node being used + AccountAddress sender = AccountAddress.from("4FbFhx5C5XaSUKdnTdrRVbtNW6rtgYYdKRJtggYGBSiktiymsX"); Expiry expiry = Expiry.createNew().addMinutes(5); + //replace with a valid sign key value from the accounts of the node being used TransactionSigner signer = TransactionSigner.from( SignerEntry.from(Index.from(0), Index.from(0), ED25519SecretKey - .from("0ee537b1eb7108a54dce9e506c3316e500c1c9997d3e83c8245cdd5fc326290f"))); + .from("b4cef1510079ba946c093826d3cf9cdd3132fa9dd8aaaf9c01442bf12d6614fd"))); var client = ClientV2.from(connection); var senderInfo = client.getAccountInfo(BlockQuery.BEST, AccountQuery.from(sender)); 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 index 3dd20dc12..6061cc3a7 100644 --- 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 @@ -33,6 +33,10 @@ @JsonSubTypes.Type( value = TransferTokenOperation.class, name = TransferTokenOperation.TYPE + ), + @JsonSubTypes.Type( + value = MintTokenOperation.class, + name = MintTokenOperation.TYPE ) }) public interface TokenOperation { diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/tokens/MintTokenOperationTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/MintTokenOperationTest.java new file mode 100644 index 000000000..310a26d8e --- /dev/null +++ b/concordium-sdk/src/test/java/com/concordium/sdk/tokens/MintTokenOperationTest.java @@ -0,0 +1,37 @@ +package com.concordium.sdk.tokens; + +import com.concordium.sdk.serializing.CborMapper; +import com.concordium.sdk.transactions.tokens.*; +import com.concordium.sdk.types.AccountAddress; +import com.concordium.sdk.types.UInt64; +import lombok.SneakyThrows; +import lombok.val; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; + +public class MintTokenOperationTest { + + @Test + @SneakyThrows + public void testMintTokenOperationSerialization() { + val operation = MintTokenOperation + .builder() + .amount(new TokenOperationAmount(UInt64.from("15"), 6)) + .build(); + val expectedHex = "bf646d696e74bf66616d6f756e74c482250fffff"; + Assert.assertEquals( + expectedHex, + Hex.toHexString(CborMapper.INSTANCE.writeValueAsBytes(operation)) + ); + Assert.assertEquals( + operation, + CborMapper.INSTANCE.readValue( + Hex.decode(expectedHex), + TokenOperation.class + ) + ); + } +} diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java index b7f7106b0..ff94d560f 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java @@ -1,9 +1,6 @@ package 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.transactions.tokens.*; import com.concordium.sdk.types.AccountAddress; import com.concordium.sdk.types.Nonce; import com.concordium.sdk.types.UInt64; @@ -230,4 +227,38 @@ public void testTokenUpdatePayloadSerialization() { TokenUpdate.fromBytes(ByteBuffer.wrap(Hex.decode(expectedHex))) ); } + + + @Test + @SneakyThrows + public void testTokenUpdateMintTransactionEnergy() { + Assert.assertEquals( + UInt64.from("692"), + TransactionFactory + .newTokenUpdate( + TokenUpdate + .builder() + .tokenSymbol("TEST") + .operation( + MintTokenOperation + .builder() + .amount( + new TokenOperationAmount( + new BigDecimal("1.5"), + 2 + ) + ) + .build() + ) + .build() + ) + .sender(AccountAddress.from("3JwD2Wm3nMbsowCwb1iGEpnt47UQgdrtnq2qT6opJc3z2AgCrc")) + .nonce(Nonce.from(78910)) + .expiry(Expiry.from(123456)) + .sign(TransactionTestHelper.getValidSigner()) + .getHeader() + .getMaxEnergyCost() + ); + } + } From 1ce039210bbf1bab92b64ed330dc13da26aa972a Mon Sep 17 00:00:00 2001 From: rba Date: Mon, 23 Feb 2026 10:56:23 +0000 Subject: [PATCH 3/6] added changelog unreleased section --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84b00b442..918c61115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased +- Added `MintTokenOperation` implementing protocol level token mint +- Added protocol level token mint example, see `MintToken` in `concordium-sdk-examples` + ## 12.1.0 - Added deserialization for the `ConfigureDelegation` payload From 18ae0a1c9297bacfdb6f578049f57aeb256fa1e7 Mon Sep 17 00:00:00 2001 From: rba Date: Mon, 23 Feb 2026 13:30:50 +0000 Subject: [PATCH 4/6] amended changelog and version to 12.1.0-alpha.2 --- CHANGELOG.md | 3 --- pom.xml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 918c61115..3f7c1c7ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,6 @@ ## Unreleased - Added `MintTokenOperation` implementing protocol level token mint - Added protocol level token mint example, see `MintToken` in `concordium-sdk-examples` - -## 12.1.0 - - Added deserialization for the `ConfigureDelegation` payload - Fixed incorrect deserialization of the `UpdateContract` payload parameter diff --git a/pom.xml b/pom.xml index 43b18a4be..4ba46ec0b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1-SNAPSHOT + 12.1.0-alpha.2 pom https://github.com/Concordium/concordium-java-sdk From b5d9fcb52a1c8402faa5861184b65eabdd19d135 Mon Sep 17 00:00:00 2001 From: rba Date: Mon, 23 Feb 2026 13:33:08 +0000 Subject: [PATCH 5/6] amended the pom xml files to contain 12.1.0-alpha.2 --- concordium-android-sdk/pom.xml | 2 +- concordium-sdk-examples/pom.xml | 2 +- concordium-sdk/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/concordium-android-sdk/pom.xml b/concordium-android-sdk/pom.xml index d85fa6003..a1644335c 100644 --- a/concordium-android-sdk/pom.xml +++ b/concordium-android-sdk/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1-SNAPSHOT + 12.1.0-alpha.2 concordium-android-sdk diff --git a/concordium-sdk-examples/pom.xml b/concordium-sdk-examples/pom.xml index e7ed42994..677ff5396 100644 --- a/concordium-sdk-examples/pom.xml +++ b/concordium-sdk-examples/pom.xml @@ -23,7 +23,7 @@ com.concordium.sdk concordium-sdk - 12.1.0-alpha.1-SNAPSHOT + 12.1.0-alpha.2 org.projectlombok diff --git a/concordium-sdk/pom.xml b/concordium-sdk/pom.xml index 50948b83f..64208ad9c 100644 --- a/concordium-sdk/pom.xml +++ b/concordium-sdk/pom.xml @@ -7,7 +7,7 @@ com.concordium.sdk concordium-sdk-base - 12.1.0-alpha.1-SNAPSHOT + 12.1.0-alpha.2 concordium-sdk From a950c9b3fba9c1deb8a4cb63c2c56118420e665f Mon Sep 17 00:00:00 2001 From: rba Date: Mon, 23 Feb 2026 13:42:16 +0000 Subject: [PATCH 6/6] amended the base energy cost for mint to be 50 --- .../concordium/sdk/transactions/tokens/MintTokenOperation.java | 2 +- .../java/com/concordium/sdk/transactions/TokenUpdateTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java index aff87250e..9c47d24eb 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/tokens/MintTokenOperation.java @@ -27,7 +27,7 @@ public class MintTokenOperation implements TokenOperation { @Override public UInt64 getBaseCost() { - return UInt64.from(100); + return UInt64.from(50); } @Override diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java index ff94d560f..360f03d6a 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TokenUpdateTest.java @@ -233,7 +233,7 @@ public void testTokenUpdatePayloadSerialization() { @SneakyThrows public void testTokenUpdateMintTransactionEnergy() { Assert.assertEquals( - UInt64.from("692"), + UInt64.from("642"), TransactionFactory .newTokenUpdate( TokenUpdate