diff --git a/.gitignore b/.gitignore
index 50e7ea6..a03eccf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+# Copyright (c) 2024, Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
lib/
diff --git a/LICENSE b/LICENSE
index e731021..387d2f8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2020 Digital Asset (Switzerland) GmbH and/or its affiliates
+ Copyright 2024 Digital Asset (Switzerland) GmbH and/or its affiliates
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/PingPong/README.rst b/PingPong/README.rst
index 7ed125c..417b6a5 100644
--- a/PingPong/README.rst
+++ b/PingPong/README.rst
@@ -3,7 +3,7 @@ Java Bindings Ping-Pong Example
::
- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+ Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
SPDX-License-Identifier: Apache-2.0.0
@@ -31,7 +31,7 @@ To set a project up:
#. If you do not have it already, install the DAML SDK by running::
- curl https://get.daml.com | sh -s 2.8.0
+ curl https://get.daml.com | sh -s 2.10.0
#. Use the start script for starting a ledger & the java application:
diff --git a/PingPong/daml.yaml b/PingPong/daml.yaml
index 99a52b5..4dd7aa0 100644
--- a/PingPong/daml.yaml
+++ b/PingPong/daml.yaml
@@ -1,11 +1,11 @@
-# Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+# Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
-sdk-version: 2.7.0
+sdk-version: 2.10.0-snapshot.20241106.0
name: ex-java-bindings
source: daml/PingPong.daml
init-script: PingPong:setup
-version: 0.0.2
+version: 1.0.0
dependencies:
- daml-prim
- daml-stdlib
@@ -13,4 +13,6 @@ dependencies:
codegen:
java:
package-prefix: examples.pingpong.codegen
- output-directory: src/main/java/
\ No newline at end of file
+ output-directory: src/main/java/
+build-options:
+ - --target=1.17
\ No newline at end of file
diff --git a/PingPong/daml/PingPong.daml b/PingPong/daml/PingPong.daml
index 4512ef1..5c87727 100644
--- a/PingPong/daml/PingPong.daml
+++ b/PingPong/daml/PingPong.daml
@@ -1,4 +1,4 @@
--- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+-- Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module PingPong where
diff --git a/PingPong/deploy.sh b/PingPong/deploy.sh
new file mode 100755
index 0000000..b92ead8
--- /dev/null
+++ b/PingPong/deploy.sh
@@ -0,0 +1,136 @@
+#!/usr/bin/env bash
+# Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+# Use absolute paths to allow this script to be called from any location
+root_dir=$(cd "$(dirname $0)"; pwd -P)
+
+clean () {
+ if [[ -d ${root_dir}/.dars ]]; then
+ rm -r ${root_dir}/.dars
+ fi
+}
+
+build () {
+ daml build
+
+ # Copy all package dars into a dedicated folder
+ mkdir -p ${root_dir}/.dars
+ cp ${root_dir}/.daml/dist/* ${root_dir}/.dars/
+}
+
+start () {
+
+ mkdir -p ${root_dir}/temp
+ output_file=$(mktemp -p ${root_dir}/temp)
+
+ pushd ${root_dir} > /dev/null || exit
+ daml sandbox > ${output_file} &
+ sandbox_pid=$!
+ popd > /dev/null || exit
+
+ echo "Sandbox running with pid: ${sandbox_pid}"
+ tail -n0 -f ${output_file} | sed '/Canton sandbox is ready/ q'
+
+ rm ${root_dir}/temp/*
+
+ echo "${sandbox_pid}" > ${root_dir}/temp/pid
+}
+
+dars() {
+ find ${root_dir}/.daml/dist -name "*${1}.dar" -exec daml ledger upload-dar --host localhost --port 6865 {} \;
+}
+
+setup () {
+ pushd ${root_dir} > /dev/null || exit
+ script_name=$(yq e '.init-script' daml.yaml)
+ script_options=$(yq e '.script-options[]' daml.yaml | tr '\n' ' ')
+ dar_name="${root_dir}/.daml/dist/ex-java-bindings-${1}.dar"
+ if [ ! -f ${dar_name} ]; then
+ echo "Setup dar not found!"
+ fi
+ echo "Running the script: ${script_name}"
+ daml script --dar ${dar_name} --script-name ${script_name} --ledger-host localhost --ledger-port 6865 ${script_options}
+ popd > /dev/null || exit
+}
+
+codegen() {
+ pushd ${root_dir} > /dev/null || exit
+ echo "Generating java code"
+ daml codegen java
+ echo "Compiling code"
+ mvn compile
+ popd > /dev/null || exit
+}
+
+grpc() {
+ pushd ${root_dir} > /dev/null || exit
+ mvn exec:java -Dexec.mainClass=examples.pingpong.grpc.PingPongGrpcMain -Dpackage.id=$packageId -Dexec.args="localhost 6865"
+ popd > /dev/null || exit
+}
+
+rx() {
+ pushd ${root_dir} > /dev/null || exit
+ mvn exec:java -Dexec.mainClass=examples.pingpong.reactive.PingPongReactiveMain -Dpackage.id=$packageId -Dexec.args="localhost 6865"
+ popd > /dev/null || exit
+}
+
+cdg() {
+ pushd ${root_dir} > /dev/null || exit
+ mvn exec:java -Dexec.mainClass=examples.pingpong.codegen.PingPongCodegenMain -Dpackage.id=$packageId -Dexec.args="localhost 6865"
+ popd > /dev/null || exit
+}
+
+stop () {
+ sandbox_pid=$(cat "${root_dir}/temp/pid")
+ echo "Stopping sandbox with pid: ${sandbox_pid}"
+ kill ${sandbox_pid}
+}
+
+operation=${1}
+extension=${2:-"1.0.0"}
+packageId=$(daml damlc inspect-dar --json ${root_dir}/.daml/dist/ex-java-bindings-${extension}.dar | jq '.main_package_id' -r)
+
+case $operation in
+ start)
+ start
+ ;;
+
+ stop)
+ stop
+ ;;
+
+ build)
+ build
+ ;;
+
+ dars)
+ dars ${extension}
+ ;;
+
+ setup)
+ setup ${extension}
+ ;;
+
+ codegen)
+ codegen
+ ;;
+
+ grpc)
+ grpc
+ ;;
+
+ rx)
+ rx
+ ;;
+
+ cdg)
+ cdg
+ ;;
+
+ up)
+ start
+ dars ${extension}
+ setup ${extension}
+
+esac
diff --git a/PingPong/pom.xml b/PingPong/pom.xml
index 772092c..d3845f5 100644
--- a/PingPong/pom.xml
+++ b/PingPong/pom.xml
@@ -5,13 +5,13 @@
com.daml.ledger.examples
example-ping-pong-java
jar
- 0.0.1-SNAPSHOT
+ 1.0.0-SNAPSHOT
UTF-8
11
11
- 2.7.0
+ 2.10.0-snapshot.20241106.13056.0.v910c3af2
diff --git a/PingPong/src/main/java/examples/pingpong/codegen/PingPongCodegenMain.java b/PingPong/src/main/java/examples/pingpong/codegen/PingPongCodegenMain.java
index 0431c3e..74ef1d5 100644
--- a/PingPong/src/main/java/examples/pingpong/codegen/PingPongCodegenMain.java
+++ b/PingPong/src/main/java/examples/pingpong/codegen/PingPongCodegenMain.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.codegen;
@@ -21,6 +21,7 @@
import io.grpc.ManagedChannelBuilder;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
public class PingPongCodegenMain {
@@ -47,24 +48,21 @@ public static void main(String[] args) {
// Initialize a plaintext gRPC channel
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
- // fetch the ledger ID, which is used in subsequent requests sent to the ledger
- String ledgerId = fetchLedgerId(channel);
-
// fetch the party IDs that got created in the Daml init script
String aliceParty = fetchPartyId(channel, ALICE_USER);
String bobParty = fetchPartyId(channel, BOB_USER);
// initialize the ping pong processors for Alice and Bob
- PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, ledgerId, channel);
- PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, ledgerId, channel);
+ PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, channel);
+ PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, channel);
// start the processors asynchronously
aliceProcessor.runIndefinitely();
bobProcessor.runIndefinitely();
// send the initial commands for both parties
- createInitialContracts(channel, ledgerId, aliceParty, bobParty, numInitialContracts);
- createInitialContracts(channel, ledgerId, bobParty, aliceParty, numInitialContracts);
+ createInitialContracts(channel, aliceParty, bobParty, numInitialContracts);
+ createInitialContracts(channel, bobParty, aliceParty, numInitialContracts);
try {
@@ -80,12 +78,11 @@ public static void main(String[] args) {
* Creates numContracts number of Ping contracts. The sender is used as the submitting party.
*
* @param channel the gRPC channel to use for services
- * @param ledgerId the previously fetched ledger id
* @param sender the party that sends the initial Ping contract
* @param receiver the party that receives the initial Ping contract
* @param numContracts the number of initial contracts to create
*/
- private static void createInitialContracts(ManagedChannel channel, String ledgerId, String sender, String receiver, int numContracts) {
+ private static void createInitialContracts(ManagedChannel channel, String sender, String receiver, int numContracts) {
CommandSubmissionServiceFutureStub submissionService = CommandSubmissionServiceGrpc.newFutureStub(channel);
for (int i = 0; i < numContracts; i++) {
@@ -102,24 +99,12 @@ private static void createInitialContracts(ManagedChannel channel, String ledger
.withWorkflowId(String.format("Ping-%s-%d", sender, i));
// convert the command submission to a proto data structure
- final var request = SubmitRequest.toProto(ledgerId, commandsSubmission);
+ final var request = SubmitRequest.toProto("", commandsSubmission);
// asynchronously send the request
submissionService.submit(request);
}
}
- /**
- * Fetches the ledger id via the Ledger Identity Service.
- *
- * @param channel the gRPC channel to use for services
- * @return the ledger id as provided by the ledger
- */
- private static String fetchLedgerId(ManagedChannel channel) {
- LedgerIdentityServiceBlockingStub ledgerIdService = LedgerIdentityServiceGrpc.newBlockingStub(channel);
- GetLedgerIdentityResponse identityResponse = ledgerIdService.getLedgerIdentity(GetLedgerIdentityRequest.getDefaultInstance());
- return identityResponse.getLedgerId();
- }
-
private static String fetchPartyId(ManagedChannel channel, String userId) {
UserManagementServiceBlockingStub userManagementService = UserManagementServiceGrpc.newBlockingStub(channel);
GetUserResponse getUserResponse = userManagementService.getUser(GetUserRequest.newBuilder().setUserId(userId).build());
diff --git a/PingPong/src/main/java/examples/pingpong/codegen/PingPongProcessor.java b/PingPong/src/main/java/examples/pingpong/codegen/PingPongProcessor.java
index de4e105..2327832 100644
--- a/PingPong/src/main/java/examples/pingpong/codegen/PingPongProcessor.java
+++ b/PingPong/src/main/java/examples/pingpong/codegen/PingPongProcessor.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.codegen;
@@ -33,7 +33,6 @@
public class PingPongProcessor {
private final String party;
- private final String ledgerId;
private final TransactionServiceStub transactionService;
private final CommandSubmissionServiceBlockingStub submissionService;
@@ -41,9 +40,8 @@ public class PingPongProcessor {
private final Identifier pingIdentifier;
private final Identifier pongIdentifier;
- public PingPongProcessor(String party, String ledgerId, ManagedChannel channel) {
+ public PingPongProcessor(String party, ManagedChannel channel) {
this.party = party;
- this.ledgerId = ledgerId;
this.transactionService = TransactionServiceGrpc.newStub(channel);
this.submissionService = CommandSubmissionServiceGrpc.newBlockingStub(channel);
this.pingIdentifier = Ping.TEMPLATE_ID;
@@ -58,8 +56,8 @@ public void runIndefinitely() {
final var filtersByParty = new FiltersByParty(Map.of(party, inclusiveFilter));
// assemble the request for the transaction stream
final var getTransactionsRequest = new GetTransactionsRequest(
- ledgerId,
- LedgerOffset.LedgerBegin.getInstance(),
+ "",
+ LedgerOffset.LedgerEnd.getInstance(),
filtersByParty,
true
);
@@ -105,7 +103,7 @@ private void processTransaction(Transaction tx) {
.withActAs(List.of(party))
.withReadAs(List.of(party))
.withWorkflowId(tx.getWorkflowId());
- submissionService.submit(SubmitRequest.toProto(ledgerId, commandsSubmission));
+ submissionService.submit(SubmitRequest.toProto("", commandsSubmission));
}
}
diff --git a/PingPong/src/main/java/examples/pingpong/grpc/IdentifierCreator.java b/PingPong/src/main/java/examples/pingpong/grpc/IdentifierCreator.java
new file mode 100644
index 0000000..025a385
--- /dev/null
+++ b/PingPong/src/main/java/examples/pingpong/grpc/IdentifierCreator.java
@@ -0,0 +1,47 @@
+package examples.pingpong.grpc;
+
+import com.daml.ledger.javaapi.data.Identifier;
+
+public class IdentifierCreator {
+ private String packageId;
+ private static String packageName = "#ex-java-bindings";
+ public IdentifierCreator(String packageId) {
+ this.packageId = packageId;
+ }
+ public Identifier pingIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageName)
+ .setModuleName("PingPong")
+ .setEntityName("Ping")
+ .build()
+ );
+ }
+ public Identifier pinnedPingIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageId)
+ .setModuleName("PingPong")
+ .setEntityName("Ping")
+ .build()
+ );
+ }
+ public Identifier pongIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageName)
+ .setModuleName("PingPong")
+ .setEntityName("Pong")
+ .build()
+ );
+ }
+ public Identifier pinnedPongIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageId)
+ .setModuleName("PingPong")
+ .setEntityName("Pong")
+ .build()
+ );
+ }
+}
diff --git a/PingPong/src/main/java/examples/pingpong/grpc/PingPongGrpcMain.java b/PingPong/src/main/java/examples/pingpong/grpc/PingPongGrpcMain.java
index aab2ebc..6890f25 100644
--- a/PingPong/src/main/java/examples/pingpong/grpc/PingPongGrpcMain.java
+++ b/PingPong/src/main/java/examples/pingpong/grpc/PingPongGrpcMain.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.grpc;
@@ -52,38 +52,24 @@ public static void main(String[] args) {
// Initialize a plaintext gRPC channel
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
- // fetch the ledger ID, which is used in subsequent requests sent to the ledger
- String ledgerId = fetchLedgerId(channel);
-
// fetch the party IDs that got created in the Daml init script
String aliceParty = fetchPartyId(channel, ALICE_USER);
String bobParty = fetchPartyId(channel, BOB_USER);
String packageId = Optional.ofNullable(System.getProperty("package.id"))
.orElseThrow(() -> new RuntimeException("package.id must be specified via sys properties"));
-
- Identifier pingIdentifier = Identifier.newBuilder()
- .setPackageId(packageId)
- .setModuleName("PingPong")
- .setEntityName("Ping")
- .build();
- Identifier pongIdentifier = Identifier.newBuilder()
- .setPackageId(packageId)
- .setModuleName("PingPong")
- .setEntityName("Pong")
- .build();
-
+ IdentifierCreator identifierCreator = new IdentifierCreator(packageId);
// initialize the ping pong processors for Alice and Bob
- PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, ledgerId, channel, pingIdentifier, pongIdentifier);
- PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, ledgerId, channel, pingIdentifier, pongIdentifier);
+ PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, channel, identifierCreator);
+ PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, channel, identifierCreator);
// start the processors asynchronously
aliceProcessor.runIndefinitely();
bobProcessor.runIndefinitely();
// send the initial commands for both parties
- createInitialContracts(channel, ledgerId, aliceParty, bobParty, pingIdentifier, numInitialContracts);
- createInitialContracts(channel, ledgerId, bobParty, aliceParty, pingIdentifier, numInitialContracts);
+ createInitialContracts(channel, aliceParty, bobParty, identifierCreator, numInitialContracts);
+ createInitialContracts(channel, bobParty, aliceParty, identifierCreator, numInitialContracts);
try {
@@ -99,24 +85,24 @@ public static void main(String[] args) {
* Creates numContracts number of Ping contracts. The sender is used as the submitting party.
*
* @param channel the gRPC channel to use for services
- * @param ledgerId the previously fetched ledger id
* @param sender the party that sends the initial Ping contract
* @param receiver the party that receives the initial Ping contract
* @param pingIdentifier the PingPong.Ping template identifier
* @param numContracts the number of initial contracts to create
*/
- private static void createInitialContracts(ManagedChannel channel, String ledgerId, String sender, String receiver, Identifier pingIdentifier, int numContracts) {
+ private static void createInitialContracts(ManagedChannel channel, String sender, String receiver,
+ IdentifierCreator identifierCreator, int numContracts) {
CommandSubmissionServiceFutureStub submissionService = CommandSubmissionServiceGrpc.newFutureStub(channel);
for (int i = 0; i < numContracts; i++) {
// command that creates the initial Ping contract with the required parameters according to the model
Command createCommand = Command.newBuilder().setCreate(
CreateCommand.newBuilder()
- .setTemplateId(pingIdentifier)
+ .setTemplateId(identifierCreator.pingIdentifier().toProto())
.setCreateArguments(
Record.newBuilder()
// the identifier for a template's record is the same as the identifier for the template
- .setRecordId(pingIdentifier)
+ .setRecordId(identifierCreator.pinnedPingIdentifier().toProto())
.addFields(RecordField.newBuilder().setLabel("sender").setValue(Value.newBuilder().setParty(sender)))
.addFields(RecordField.newBuilder().setLabel("receiver").setValue(Value.newBuilder().setParty(receiver)))
.addFields(RecordField.newBuilder().setLabel("count").setValue(Value.newBuilder().setInt64(0)))
@@ -125,7 +111,6 @@ private static void createInitialContracts(ManagedChannel channel, String ledger
SubmitRequest submitRequest = SubmitRequest.newBuilder().setCommands(Commands.newBuilder()
- .setLedgerId(ledgerId)
.setCommandId(UUID.randomUUID().toString())
.setWorkflowId(String.format("Ping-%s-%d", sender, i))
.setParty(sender)
@@ -138,18 +123,6 @@ private static void createInitialContracts(ManagedChannel channel, String ledger
}
}
- /**
- * Fetches the ledger id via the Ledger Identity Service.
- *
- * @param channel the gRPC channel to use for services
- * @return the ledger id as provided by the ledger
- */
- private static String fetchLedgerId(ManagedChannel channel) {
- LedgerIdentityServiceBlockingStub ledgerIdService = LedgerIdentityServiceGrpc.newBlockingStub(channel);
- GetLedgerIdentityResponse identityResponse = ledgerIdService.getLedgerIdentity(GetLedgerIdentityRequest.getDefaultInstance());
- return identityResponse.getLedgerId();
- }
-
private static String fetchPartyId(ManagedChannel channel, String userId) {
UserManagementServiceBlockingStub userManagementService = UserManagementServiceGrpc.newBlockingStub(channel);
GetUserResponse getUserResponse = userManagementService.getUser(GetUserRequest.newBuilder().setUserId(userId).build());
diff --git a/PingPong/src/main/java/examples/pingpong/grpc/PingPongProcessor.java b/PingPong/src/main/java/examples/pingpong/grpc/PingPongProcessor.java
index 1c7785d..e3c3997 100644
--- a/PingPong/src/main/java/examples/pingpong/grpc/PingPongProcessor.java
+++ b/PingPong/src/main/java/examples/pingpong/grpc/PingPongProcessor.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.grpc;
@@ -40,21 +40,17 @@
public class PingPongProcessor {
private final String party;
- private final String ledgerId;
-
+
private final TransactionServiceStub transactionService;
private final CommandSubmissionServiceBlockingStub submissionService;
- private final Identifier pingIdentifier;
- private final Identifier pongIdentifier;
+ private final IdentifierCreator identifierCreator;
- public PingPongProcessor(String party, String ledgerId, ManagedChannel channel, Identifier pingIdentifier, Identifier pongIdentifier) {
+ public PingPongProcessor(String party, ManagedChannel channel, IdentifierCreator identifierCreator) {
this.party = party;
- this.ledgerId = ledgerId;
this.transactionService = TransactionServiceGrpc.newStub(channel);
this.submissionService = CommandSubmissionServiceGrpc.newBlockingStub(channel);
- this.pingIdentifier = pingIdentifier;
- this.pongIdentifier = pongIdentifier;
+ this.identifierCreator = identifierCreator;
}
public void runIndefinitely() {
@@ -64,14 +60,13 @@ public void runIndefinitely() {
Filters.newBuilder()
.setInclusive(
InclusiveFilters.newBuilder()
- .addTemplateIds(pingIdentifier)
- .addTemplateIds(pongIdentifier)
+ .addTemplateIds(identifierCreator.pingIdentifier().toProto())
+ .addTemplateIds(identifierCreator.pongIdentifier().toProto())
.build())
.build());
// assemble the request for the transaction stream
GetTransactionsRequest transactionsRequest = GetTransactionsRequest.newBuilder()
- .setLedgerId(ledgerId)
- .setBegin(LedgerOffset.newBuilder().setBoundary(LedgerBoundary.LEDGER_BEGIN))
+ .setBegin(LedgerOffset.newBuilder().setBoundary(LedgerBoundary.LEDGER_END))
.setFilter(filtersByParty)
.setVerbose(true)
.build();
@@ -114,7 +109,6 @@ private void processTransaction(Transaction tx) {
.setCommands(Commands.newBuilder()
.setCommandId(UUID.randomUUID().toString())
.setWorkflowId(tx.getWorkflowId())
- .setLedgerId(ledgerId)
.setParty(party)
.setApplicationId(PingPongGrpcMain.APP_ID)
.addAllCommands(commands)
@@ -137,10 +131,10 @@ private void processTransaction(Transaction tx) {
private Stream processEvent(String workflowId, CreatedEvent event) {
Identifier template = event.getTemplateId();
- boolean isPingPongModule = template.getModuleName().equals(pingIdentifier.getModuleName());
+ boolean isPingPongModule = template.getModuleName().equals(identifierCreator.pingIdentifier().getModuleName());
- boolean isPing = template.getEntityName().equals(pingIdentifier.getEntityName());
- boolean isPong = template.getEntityName().equals(pongIdentifier.getEntityName());
+ boolean isPing = template.getEntityName().equals(identifierCreator.pingIdentifier().getEntityName());
+ boolean isPong = template.getEntityName().equals(identifierCreator.pongIdentifier().getEntityName());
if (!isPingPongModule || !isPing && !isPong) return Stream.empty();
diff --git a/PingPong/src/main/java/examples/pingpong/reactive/IdentifierCreator.java b/PingPong/src/main/java/examples/pingpong/reactive/IdentifierCreator.java
new file mode 100644
index 0000000..e59cc0f
--- /dev/null
+++ b/PingPong/src/main/java/examples/pingpong/reactive/IdentifierCreator.java
@@ -0,0 +1,47 @@
+package examples.pingpong.reactive;
+
+import com.daml.ledger.javaapi.data.Identifier;
+
+public class IdentifierCreator {
+ private String packageId;
+ private static String packageName = "#ex-java-bindings";
+ public IdentifierCreator(String packageId) {
+ this.packageId = packageId;
+ }
+ public Identifier pingIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageName)
+ .setModuleName("PingPong")
+ .setEntityName("Ping")
+ .build()
+ );
+ }
+ public Identifier pinnedPingIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageId)
+ .setModuleName("PingPong")
+ .setEntityName("Ping")
+ .build()
+ );
+ }
+ public Identifier pongIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageName)
+ .setModuleName("PingPong")
+ .setEntityName("Pong")
+ .build()
+ );
+ }
+ public Identifier pinnedPongIdentifier() {
+ return Identifier.fromProto(
+ com.daml.ledger.api.v1.ValueOuterClass.Identifier.newBuilder()
+ .setPackageId(packageId)
+ .setModuleName("PingPong")
+ .setEntityName("Pong")
+ .build()
+ );
+ }
+}
diff --git a/PingPong/src/main/java/examples/pingpong/reactive/PingPongProcessor.java b/PingPong/src/main/java/examples/pingpong/reactive/PingPongProcessor.java
index 2c87105..ed37660 100644
--- a/PingPong/src/main/java/examples/pingpong/reactive/PingPongProcessor.java
+++ b/PingPong/src/main/java/examples/pingpong/reactive/PingPongProcessor.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.reactive;
@@ -26,18 +26,14 @@ public class PingPongProcessor {
private static final Logger logger = LoggerFactory.getLogger(PingPongProcessor.class);
private final String party;
- private final String ledgerId;
private LedgerClient client;
- private final Identifier pingIdentifier;
- private final Identifier pongIdentifier;
+ private final IdentifierCreator identifierCreator;
- public PingPongProcessor(String party, LedgerClient client, Identifier pingIdentifier, Identifier pongIdentifier) {
+ public PingPongProcessor(String party, LedgerClient client, IdentifierCreator identifierCreator) {
this.party = party;
- this.ledgerId = client.getLedgerId();
this.client = client;
- this.pingIdentifier = pingIdentifier;
- this.pongIdentifier = pongIdentifier;
+ this.identifierCreator = identifierCreator;
}
public void runIndefinitely() {
@@ -84,8 +80,8 @@ private Single processTransaction(Transaction tx) {
private Stream processEvent(String workflowId, CreatedEvent event) {
Identifier template = event.getTemplateId();
- boolean isPing = template.equals(pingIdentifier);
- boolean isPong = template.equals(pongIdentifier);
+ boolean isPing = template.getEntityName().equals(identifierCreator.pingIdentifier().getEntityName());
+ boolean isPong = template.getEntityName().equals(identifierCreator.pongIdentifier().getEntityName());
if (!isPing && !isPong) return Stream.empty();
diff --git a/PingPong/src/main/java/examples/pingpong/reactive/PingPongReactiveMain.java b/PingPong/src/main/java/examples/pingpong/reactive/PingPongReactiveMain.java
index 092be9d..83adb1a 100644
--- a/PingPong/src/main/java/examples/pingpong/reactive/PingPongReactiveMain.java
+++ b/PingPong/src/main/java/examples/pingpong/reactive/PingPongReactiveMain.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package examples.pingpong.reactive;
@@ -9,7 +9,6 @@
import com.daml.ledger.api.v1.CommandsOuterClass.Command;
import com.daml.ledger.api.v1.CommandsOuterClass.CreateCommand;
-import com.daml.ledger.api.v1.ValueOuterClass.Identifier;
import com.daml.ledger.api.v1.ValueOuterClass.Record;
import com.daml.ledger.api.v1.ValueOuterClass.RecordField;
import com.daml.ledger.api.v1.ValueOuterClass.Value;
@@ -54,21 +53,18 @@ public static void main(String[] args) {
String bobParty = userManagementClient.getUser(new GetUserRequest(BOB_USER)).blockingGet().getUser().getPrimaryParty().get();
String packageId = Optional.ofNullable(System.getProperty("package.id")).orElseThrow(() -> new RuntimeException("package.id must be specified via sys properties"));
- var pingIdentifier = com.daml.ledger.javaapi.data.Identifier.fromProto(Identifier.newBuilder()
- .setPackageId(packageId).setModuleName("PingPong").setEntityName("Ping").build());
- var pongIdentifier = com.daml.ledger.javaapi.data.Identifier.fromProto(Identifier.newBuilder()
- .setPackageId(packageId).setModuleName("PingPong").setEntityName("Pong").build());
+ IdentifierCreator identifierCreator = new IdentifierCreator(packageId);
// initialize the ping pong processors for Alice and Bob
- PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, client, pingIdentifier, pongIdentifier);
- PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, client, pingIdentifier, pongIdentifier);
+ PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, client, identifierCreator);
+ PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, client, identifierCreator);
// start the processors asynchronously
aliceProcessor.runIndefinitely();
bobProcessor.runIndefinitely();
// send the initial commands for both parties
- createInitialContracts(client, aliceParty, bobParty, pingIdentifier.toProto(), numInitialContracts);
- createInitialContracts(client, bobParty, aliceParty, pingIdentifier.toProto(), numInitialContracts);
+ createInitialContracts(client, aliceParty, bobParty, identifierCreator, numInitialContracts);
+ createInitialContracts(client, bobParty, aliceParty, identifierCreator, numInitialContracts);
try {
// wait a couple of seconds for the processing to finish
@@ -90,7 +86,7 @@ public static void main(String[] args) {
* @param numContracts the number of initial contracts to create
*/
private static void createInitialContracts(LedgerClient client, String sender, String receiver,
- Identifier pingIdentifier, int numContracts) {
+ IdentifierCreator identifierCreator, int numContracts) {
for (int i = 0; i < numContracts; i++) {
// command that creates the initial Ping contract with the required parameters
@@ -98,12 +94,12 @@ private static void createInitialContracts(LedgerClient client, String sender, S
Command createCommand = Command.newBuilder().setCreate(
CreateCommand.newBuilder()
- .setTemplateId(pingIdentifier)
+ .setTemplateId(identifierCreator.pingIdentifier().toProto())
.setCreateArguments(
Record.newBuilder()
// the identifier for a template's record is the same as the identifier for
// the template
- .setRecordId(pingIdentifier)
+ .setRecordId(identifierCreator.pinnedPingIdentifier().toProto())
.addFields(RecordField.newBuilder().setLabel("sender")
.setValue(Value.newBuilder().setParty(sender)))
.addFields(RecordField.newBuilder().setLabel("receiver")
diff --git a/PingPong/src/main/resources/logback.xml b/PingPong/src/main/resources/logback.xml
index 2ae760b..3801900 100644
--- a/PingPong/src/main/resources/logback.xml
+++ b/PingPong/src/main/resources/logback.xml
@@ -1,5 +1,5 @@
diff --git a/PingPong/start.sh b/PingPong/start.sh
index fc34251..3d857c3 100755
--- a/PingPong/start.sh
+++ b/PingPong/start.sh
@@ -16,7 +16,7 @@ trap cleanup ERR EXIT
echo "Compiling daml"
daml build
-packageId=$(daml damlc inspect-dar --json .daml/dist/ex-java-bindings-0.0.2.dar | jq '.main_package_id' -r)
+packageId=$(daml damlc inspect-dar --json .daml/dist/ex-java-bindings-1.0.0.dar | jq '.main_package_id' -r)
echo "Generating java code"
diff --git a/README.rst b/README.rst
index cf4fa95..dbefad3 100644
--- a/README.rst
+++ b/README.rst
@@ -3,7 +3,7 @@ Java Bindings Examples
::
- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+ Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
SPDX-License-Identifier: Apache-2.0.0
This repository contains two subprojects that demonstrate building of Daml client applications with the usage of Java Bindings:
diff --git a/StockExchange/README.rst b/StockExchange/README.rst
index 33b3499..87cbb34 100644
--- a/StockExchange/README.rst
+++ b/StockExchange/README.rst
@@ -3,7 +3,7 @@ Example of Explicit Disclosure with Java Bindings
::
- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+ Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
SPDX-License-Identifier: Apache-2.0.0
This project demonstrates the usage of `Explicit Contract Disclosure `_
@@ -50,6 +50,10 @@ Running the example
start_canton
+#. In the first terminal, upload the package to all participant nodes
+
+ upload_package
+
#. In the first terminal, run the example
run_stock_exchange
diff --git a/StockExchange/canton_ledger.conf b/StockExchange/canton_ledger.conf
index fff451b..c86fc06 100644
--- a/StockExchange/canton_ledger.conf
+++ b/StockExchange/canton_ledger.conf
@@ -4,21 +4,37 @@ canton {
storage.type = memory
admin-api.port = 5012
ledger-api.port = 5011
+ parameters {
+ initial-protocol-version = 7
+ dev-version-support = yes
+ }
}
bankParticipant {
storage.type = memory
admin-api.port = 5022
ledger-api.port = 5021
+ parameters {
+ initial-protocol-version = 7
+ dev-version-support = yes
+ }
}
buyerParticipant {
storage.type = memory
admin-api.port = 5032
ledger-api.port = 5031
+ parameters {
+ initial-protocol-version = 7
+ dev-version-support = yes
+ }
}
sellerParticipant {
storage.type = memory
admin-api.port = 5042
ledger-api.port = 5041
+ parameters {
+ initial-protocol-version = 7
+ dev-version-support = yes
+ }
}
}
domains {
@@ -26,8 +42,13 @@ canton {
storage.type = memory
public-api.port = 5018
admin-api.port = 5019
+ init.domain-parameters.protocol-version=7
}
}
// enable ledger_api commands for setup simplicity of the Ledger API
features.enable-testing-commands = yes
+ parameters {
+ non-standard-config = yes
+ dev-version-support = yes
+ }
}
diff --git a/StockExchange/daml.yaml b/StockExchange/daml.yaml
index ab97dca..8eaac67 100644
--- a/StockExchange/daml.yaml
+++ b/StockExchange/daml.yaml
@@ -1,10 +1,10 @@
-# Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
+# Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
-sdk-version: 2.8.0
+sdk-version: 2.10.0-snapshot.20241106.0
name: ex-java-bindings-stock-exchange
source: daml/StockExchange.daml
-version: 0.0.1
+version: 1.0.0
dependencies:
- daml-prim
- daml-stdlib
@@ -12,3 +12,5 @@ codegen:
java:
package-prefix: examples.codegen
output-directory: src/main/java/
+build-options:
+ - --target=1.17
\ No newline at end of file
diff --git a/StockExchange/pom.xml b/StockExchange/pom.xml
index ceac89f..94e1dc7 100644
--- a/StockExchange/pom.xml
+++ b/StockExchange/pom.xml
@@ -5,13 +5,13 @@
com.daml.ledger.examples
example-stock-exchange-java
jar
- 0.0.1-SNAPSHOT
+ 1.0.0-SNAPSHOT
UTF-8
11
11
- 2.8.0
+ 2.10.0-snapshot.20241106.13056.0.v910c3af2
diff --git a/StockExchange/setup.sh b/StockExchange/setup.sh
index d38e58c..27d216b 100755
--- a/StockExchange/setup.sh
+++ b/StockExchange/setup.sh
@@ -22,6 +22,15 @@ function start_canton() {
fi
}
+function upload_package() {
+ version=${1:-"1.0.0"}
+ for port in 5011 5021 5031 5041 ;
+ do
+ daml ledger upload-dar --host localhost --port "${port}" .daml/dist/ex-java-bindings-stock-exchange-"${version}".dar
+ done
+
+}
+
function run_stock_exchange() {
echo "Running StockExchange"
stockExchangePartiesFile="temp_stock_exchange_example/stock_exchange_parties.txt"
diff --git a/StockExchange/src/main/resources/logback.xml b/StockExchange/src/main/resources/logback.xml
index 8e5bd40..f732342 100644
--- a/StockExchange/src/main/resources/logback.xml
+++ b/StockExchange/src/main/resources/logback.xml
@@ -1,5 +1,5 @@
diff --git a/StockExchange/stock_exchange_bootstrap_script.canton b/StockExchange/stock_exchange_bootstrap_script.canton
index 3edc952..01019ad 100644
--- a/StockExchange/stock_exchange_bootstrap_script.canton
+++ b/StockExchange/stock_exchange_bootstrap_script.canton
@@ -21,15 +21,15 @@ val buyer = buyerParticipant.parties.enable("buyer")
val seller = sellerParticipant.parties.enable("seller")
// Write party ids to a file for allowing easy discovery
-val partiesFileContent = s"${stockExchange.toPrim}\n${bank.toPrim}\n${buyer.toPrim}\n${seller.toPrim}"
+val partiesFileContent = s"${stockExchange.toProtoPrimitive}\n${bank.toProtoPrimitive}\n${buyer.toProtoPrimitive}\n${seller.toProtoPrimitive}"
Files.createDirectories(Paths.get("temp_stock_exchange_example"));
Files.write(Paths.get("temp_stock_exchange_example/stock_exchange_parties.txt"), partiesFileContent.getBytes(StandardCharsets.UTF_8))
println("Waiting for the parties to appear on their hosting participants' Ledger API...")
-utils.retry_until_true(buyerParticipant.ledger_api.parties.list().exists(_.party.toPrim.toString.startsWith("buyer::")))
-utils.retry_until_true(sellerParticipant.ledger_api.parties.list().exists(_.party.toPrim.toString.startsWith("seller::")))
-utils.retry_until_true(bankParticipant.ledger_api.parties.list().exists(_.party.toPrim.toString.startsWith("bank::")))
-utils.retry_until_true(stockExchangeParticipant.ledger_api.parties.list().exists(_.party.toPrim.toString.startsWith("stockExchange::")))
+utils.retry_until_true(buyerParticipant.ledger_api.parties.list().exists(_.party.toProtoPrimitive.toString.startsWith("buyer::")))
+utils.retry_until_true(sellerParticipant.ledger_api.parties.list().exists(_.party.toProtoPrimitive.toString.startsWith("seller::")))
+utils.retry_until_true(bankParticipant.ledger_api.parties.list().exists(_.party.toProtoPrimitive.toString.startsWith("bank::")))
+utils.retry_until_true(stockExchangeParticipant.ledger_api.parties.list().exists(_.party.toProtoPrimitive.toString.startsWith("stockExchange::")))
stockExchangeParticipant.ledger_api.users.create("StockExchange", actAs = Set(stockExchange), primaryParty = Some(stockExchange))
bankParticipant.ledger_api.users.create("Bank", actAs = Set(bank), primaryParty = Some(bank))