Convert rx java to use LAPI v2 (#18341)

* use state service

eliminate ledger-identity and ledger-configuration services

update service

event query and package services

command service

command completions

command submission service

time service

clean-up

* fix documentation example

* format

* adopt rx to changed java-bindings
This commit is contained in:
mziolekda 2024-02-01 14:48:54 +01:00 committed by GitHub
parent b315b87755
commit f0de92ba10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 1943 additions and 2688 deletions

View File

@ -493,19 +493,16 @@ packages/bindings-java-tutorial/static/com/daml/ledger/javaapi/data/InclusiveFil
packages/bindings-java-tutorial/static/com/daml/ledger/javaapi/TransactionsClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/TransactionsClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/LedgerClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/LedgerClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/CommandClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/CommandClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/LedgerIdentityClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/LedgerIdentityClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/util/FlowableLogger.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/util/FlowableLogger.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/util/package-frame.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/util/package-frame.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/util/ClientPublisherFlowable.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/util/ClientPublisherFlowable.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/util/package-summary.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/util/package-summary.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/util/package-tree.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/util/package-tree.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/CommandSubmissionClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/CommandSubmissionClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/LedgerIdentityClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/LedgerIdentityClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/LedgerConfigurationClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/LedgerConfigurationClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/CommandClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/CommandClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/TransactionClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/TransactionClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/UpdateClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/UpdateClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/package-frame.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/package-frame.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/ActiveContractClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/ActiveContractClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/StateClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/StateClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/package-summary.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/package-summary.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/CommandCompletionClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/CommandCompletionClientImpl.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/PackageClientImpl.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/PackageClientImpl.html
@ -515,7 +512,6 @@ app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/helpers/package-fram
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/helpers/package-summary.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/helpers/package-summary.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/helpers/TimestampComparator.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/helpers/TimestampComparator.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/grpc/helpers/package-tree.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/grpc/helpers/package-tree.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/LedgerConfigurationClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/LedgerConfigurationClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/CommandSubmissionClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/CommandSubmissionClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/package-frame.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/package-frame.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/package-summary.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/package-summary.html
@ -526,14 +522,12 @@ app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/Bot.html -> /a
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/CreatedContractContext.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/CreatedContractContext.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/Pair.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/Pair.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/CommandsAndPendingSet.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/CommandsAndPendingSet.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/TransactionContext.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/TransactionContext.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/GetActiveContractsResponseContext.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/GetActiveContractsResponseContext.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/package-frame.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/package-frame.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/package-summary.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/package-summary.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/package-tree.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/package-tree.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/components/helpers/CreatedContract.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/components/helpers/CreatedContract.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/package-frame.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/package-frame.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/ActiveContractsClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/ActiveContractsClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/StateClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/StateClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/TimeClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/TimeClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/DamlLedgerClient.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/DamlLedgerClient.html
app-dev/bindings-java/javadocs/com/daml/ledger/javaapi/package-tree.html -> /app-dev/bindings-java/javadocs/com/daml/ledger/rxjava/package-tree.html

View File

@ -47,22 +47,19 @@ public class IouMain {
// Connects to the ledger and runs initial validation.
client.connect();
String ledgerId = client.getLedgerId();
logger.info("ledger-id: {}", ledgerId);
AtomicLong idCounter = new AtomicLong(0);
ConcurrentHashMap<Long, Iou> contracts = new ConcurrentHashMap<>();
BiMap<Long, Iou.ContractId> idMap = Maps.synchronizedBiMap(HashBiMap.create());
AtomicReference<LedgerOffset> acsOffset =
new AtomicReference<>(LedgerOffset.LedgerBegin.getInstance());
AtomicReference<ParticipantOffsetV2> acsOffset =
new AtomicReference<>(ParticipantOffsetV2.ParticipantBegin.getInstance());
client
.getActiveContractSetClient()
.getStateClient()
.getActiveContracts(Iou.contractFilter(), Collections.singleton(party), true)
.blockingForEach(
response -> {
response.offset.ifPresent(offset -> acsOffset.set(new LedgerOffset.Absolute(offset)));
response.offset.ifPresent(
offset -> acsOffset.set(new ParticipantOffsetV2.Absolute(offset)));
response.activeContracts.forEach(
contract -> {
long id = idCounter.getAndIncrement();
@ -134,7 +131,7 @@ public class IouMain {
private static <U> U submit(LedgerClient client, String party, Update<U> update) {
var updateSubmission =
UpdateSubmission.create(APP_ID, randomUUID().toString(), update).withActAs(party);
UpdateSubmissionV2.create(APP_ID, randomUUID().toString(), update).withActAs(party);
return client.getCommandClient().submitAndWaitForResult(updateSubmission).blockingGet();
}

View File

@ -3,23 +3,23 @@
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.CommandsSubmission;
import com.daml.ledger.javaapi.data.Transaction;
import com.daml.ledger.javaapi.data.TransactionTree;
import com.daml.ledger.javaapi.data.UpdateSubmission;
import com.daml.ledger.javaapi.data.CommandsSubmissionV2;
import com.daml.ledger.javaapi.data.TransactionTreeV2;
import com.daml.ledger.javaapi.data.TransactionV2;
import com.daml.ledger.javaapi.data.UpdateSubmissionV2;
import com.google.protobuf.Empty;
import io.reactivex.Single;
import org.checkerframework.checker.nullness.qual.NonNull;
/** An RxJava version of {@link com.daml.ledger.api.v1.CommandServiceGrpc} */
/** An RxJava version of {@link com.daml.ledger.api.v2.CommandServiceGrpc} */
public interface CommandClient {
Single<Empty> submitAndWait(CommandsSubmission submission);
Single<Empty> submitAndWait(CommandsSubmissionV2 submission);
Single<String> submitAndWaitForTransactionId(CommandsSubmission submission);
Single<String> submitAndWaitForTransactionId(CommandsSubmissionV2 submission);
Single<Transaction> submitAndWaitForTransaction(CommandsSubmission submission);
Single<TransactionV2> submitAndWaitForTransaction(CommandsSubmissionV2 submission);
Single<TransactionTree> submitAndWaitForTransactionTree(CommandsSubmission submission);
Single<TransactionTreeV2> submitAndWaitForTransactionTree(CommandsSubmissionV2 submission);
<U> Single<U> submitAndWaitForResult(@NonNull UpdateSubmission<U> submission);
<U> Single<U> submitAndWaitForResult(@NonNull UpdateSubmissionV2<U> submission);
}

View File

@ -3,28 +3,22 @@
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.CompletionEndResponse;
import com.daml.ledger.javaapi.data.CompletionStreamResponse;
import com.daml.ledger.javaapi.data.LedgerOffset;
import com.daml.ledger.javaapi.data.CompletionStreamResponseV2;
import com.daml.ledger.javaapi.data.ParticipantOffsetV2;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Set;
import java.util.List;
/** An RxJava version of {@link com.daml.ledger.api.v1.CommandCompletionServiceGrpc} */
public interface CommandCompletionClient {
Flowable<CompletionStreamResponse> completionStream(
String applicationId, LedgerOffset offset, Set<String> parties);
Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, ParticipantOffsetV2 offset, List<String> parties);
Flowable<CompletionStreamResponse> completionStream(
String applicationId, LedgerOffset offset, Set<String> parties, String accessToken);
Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, ParticipantOffsetV2 offset, List<String> parties, String accessToken);
Flowable<CompletionStreamResponse> completionStream(String applicationId, Set<String> parties);
Flowable<CompletionStreamResponseV2> completionStream(String applicationId, List<String> parties);
Flowable<CompletionStreamResponse> completionStream(
String applicationId, Set<String> parties, String accessToken);
Single<CompletionEndResponse> completionEnd();
Single<CompletionEndResponse> completionEnd(String accessToken);
Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, List<String> parties, String accessToken);
}

View File

@ -3,12 +3,12 @@
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.CommandsSubmission;
import com.google.protobuf.Empty;
import com.daml.ledger.api.v2.CommandSubmissionServiceOuterClass.SubmitResponse;
import com.daml.ledger.javaapi.data.CommandsSubmissionV2;
import io.reactivex.Single;
/** An RxJava version of {@link com.daml.ledger.api.v1.CommandSubmissionServiceGrpc} */
/** An RxJava version of {@link com.daml.ledger.api.v2.CommandSubmissionServiceGrpc} */
public interface CommandSubmissionClient {
Single<Empty> submit(CommandsSubmission submission);
Single<SubmitResponse> submit(CommandsSubmissionV2 submission);
}

View File

@ -26,7 +26,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* <li>Call the method {@link DamlLedgerClient#connect()} to initialize the clients for that
* particular ledger
* <li>Retrieve one of the clients by using a getter, e.g. {@link
* DamlLedgerClient#getActiveContractSetClient()}
* DamlLedgerClient#getStateClient()}
* </ol>
*
* <p>Alternatively to {@link DamlLedgerClient#newBuilder(String, int)}, you can use {@link
@ -42,7 +42,6 @@ public final class DamlLedgerClient implements LedgerClient {
public static final class Builder {
private final NettyChannelBuilder builder;
private Optional<String> expectedLedgerId = Optional.empty();
private Optional<String> accessToken = Optional.empty();
private Optional<Duration> timeout = Optional.empty();
@ -57,18 +56,6 @@ public final class DamlLedgerClient implements LedgerClient {
return this;
}
/**
* @deprecated since 2.0 the ledger identifier has been deprecated as a fail-safe against
* contacting an unexpected participant. You are recommended to use the participant
* identifier in the access token as a way to validate that you are accessing the ledger
* through the expected participant node (as well as authorize your calls).
*/
@Deprecated
public Builder withExpectedLedgerId(@NonNull String expectedLedgerId) {
this.expectedLedgerId = Optional.of(expectedLedgerId);
return this;
}
public Builder withAccessToken(@NonNull String accessToken) {
this.accessToken = Optional.of(accessToken);
return this;
@ -80,8 +67,7 @@ public final class DamlLedgerClient implements LedgerClient {
}
public DamlLedgerClient build() {
return new DamlLedgerClient(
this.builder, this.expectedLedgerId, this.accessToken, this.timeout);
return new DamlLedgerClient(this.builder, this.accessToken, this.timeout);
}
}
@ -111,79 +97,49 @@ public final class DamlLedgerClient implements LedgerClient {
return new Builder(channelBuilder);
}
private ActiveContractsClient activeContractsClient;
private TransactionsClient transactionsClient;
private StateClient stateServiceClient;
private UpdateClient transactionsClient;
private CommandCompletionClient commandCompletionClient;
private CommandClient commandClient;
private CommandSubmissionClient commandSubmissionClient;
@Deprecated private LedgerIdentityClient ledgerIdentityClient;
private EventQueryClient eventQueryClient;
private PackageClient packageClient;
private LedgerConfigurationClient ledgerConfigurationClient;
private TimeClient timeClient;
private UserManagementClient userManagementClient;
private String expectedLedgerId;
private Optional<String> accessToken;
private final Optional<Duration> timeout;
private final ManagedChannel channel;
private DamlLedgerClient(
@NonNull NettyChannelBuilder channelBuilder,
@NonNull Optional<String> expectedLedgerId,
@NonNull Optional<String> accessToken,
@NonNull Optional<Duration> timeout) {
this.channel = channelBuilder.build();
this.expectedLedgerId = expectedLedgerId.orElse(null);
this.accessToken = accessToken;
this.timeout = timeout;
}
/** Connects this instance of the {@link DamlLedgerClient} to the Ledger. */
public void connect() {
@SuppressWarnings("deprecation")
var lic = new LedgerIdentityClientImpl(channel, this.accessToken, this.timeout);
ledgerIdentityClient = lic;
String reportedLedgerId = ledgerIdentityClient.getLedgerIdentity().blockingGet();
if (this.expectedLedgerId != null && !this.expectedLedgerId.equals(reportedLedgerId)) {
throw new IllegalArgumentException(
String.format(
"Configured ledger id [%s] is not the same as reported by the ledger [%s]",
this.expectedLedgerId, reportedLedgerId));
} else {
this.expectedLedgerId = reportedLedgerId;
}
activeContractsClient =
new ActiveContractClientImpl(reportedLedgerId, channel, pool, this.accessToken);
transactionsClient =
new TransactionClientImpl(reportedLedgerId, channel, pool, this.accessToken);
commandCompletionClient =
new CommandCompletionClientImpl(reportedLedgerId, channel, pool, this.accessToken);
stateServiceClient = new StateClientImpl(channel, pool, this.accessToken);
transactionsClient = new UpdateClientImpl(channel, pool, this.accessToken);
commandCompletionClient = new CommandCompletionClientImpl(channel, pool, this.accessToken);
commandSubmissionClient =
new CommandSubmissionClientImpl(reportedLedgerId, channel, this.accessToken, this.timeout);
commandClient = new CommandClientImpl(reportedLedgerId, channel, this.accessToken);
new CommandSubmissionClientImpl(channel, this.accessToken, this.timeout);
commandClient = new CommandClientImpl(channel, this.accessToken);
eventQueryClient = new EventQueryClientImpl(channel, this.accessToken);
packageClient = new PackageClientImpl(reportedLedgerId, channel, this.accessToken);
ledgerConfigurationClient =
new LedgerConfigurationClientImpl(reportedLedgerId, channel, pool, this.accessToken);
timeClient = new TimeClientImpl(reportedLedgerId, channel, pool, this.accessToken);
packageClient = new PackageClientImpl(channel, this.accessToken);
timeClient = new TimeClientImpl(channel, pool, this.accessToken);
userManagementClient = new UserManagementClientImpl(channel, this.accessToken);
}
@Override
public String getLedgerId() {
return expectedLedgerId;
public StateClient getStateClient() {
return stateServiceClient;
}
@Override
public ActiveContractsClient getActiveContractSetClient() {
return activeContractsClient;
}
@Override
public TransactionsClient getTransactionsClient() {
public UpdateClient getTransactionsClient() {
return transactionsClient;
}
@ -202,12 +158,6 @@ public final class DamlLedgerClient implements LedgerClient {
return commandSubmissionClient;
}
@Deprecated
@Override
public LedgerIdentityClient getLedgerIdentityClient() {
return ledgerIdentityClient;
}
@Override
public EventQueryClient getEventQueryClient() {
return eventQueryClient;
@ -218,11 +168,6 @@ public final class DamlLedgerClient implements LedgerClient {
return packageClient;
}
@Override
public LedgerConfigurationClient getLedgerConfigurationClient() {
return ledgerConfigurationClient;
}
@Override
public TimeClient getTimeClient() {
return timeClient;

View File

@ -3,31 +3,15 @@
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.GetEventsByContractIdResponse;
import com.daml.ledger.javaapi.data.GetEventsByContractKeyResponse;
import com.daml.ledger.javaapi.data.Identifier;
import com.daml.ledger.javaapi.data.Value;
import com.daml.ledger.javaapi.data.GetEventsByContractIdResponseV2;
import io.reactivex.Single;
import java.util.Set;
/** An RxJava version of {@link com.daml.ledger.api.v1.PackageServiceGrpc} */
public interface EventQueryClient {
Single<GetEventsByContractIdResponse> getEventsByContractId(
Single<GetEventsByContractIdResponseV2> getEventsByContractId(
String contractId, Set<String> requestingParties);
Single<GetEventsByContractIdResponse> getEventsByContractId(
Single<GetEventsByContractIdResponseV2> getEventsByContractId(
String contractId, Set<String> requestingParties, String accessToken);
Single<GetEventsByContractKeyResponse> getEventsByContractKey(
Value contractKey,
Identifier templateId,
Set<String> requestingParties,
String continuationToken);
Single<GetEventsByContractKeyResponse> getEventsByContractKey(
Value contractKey,
Identifier templateId,
Set<String> requestingParties,
String continuationToken,
String accessToken);
}

View File

@ -7,11 +7,9 @@ package com.daml.ledger.rxjava;
public interface LedgerClient {
/** @return The identifier of the Ledger connected to this {@link LedgerClient} */
String getLedgerId();
StateClient getStateClient();
ActiveContractsClient getActiveContractSetClient();
TransactionsClient getTransactionsClient();
UpdateClient getTransactionsClient();
CommandClient getCommandClient();
@ -19,15 +17,10 @@ public interface LedgerClient {
CommandSubmissionClient getCommandSubmissionClient();
@Deprecated
LedgerIdentityClient getLedgerIdentityClient();
EventQueryClient getEventQueryClient();
PackageClient getPackageClient();
LedgerConfigurationClient getLedgerConfigurationClient();
TimeClient getTimeClient();
UserManagementClient getUserManagementClient();

View File

@ -1,16 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava;
import com.daml.ledger.api.v1.LedgerConfigurationServiceOuterClass;
import io.reactivex.Flowable;
/** An RxJava version of {@link com.daml.ledger.api.v1.LedgerConfigurationServiceGrpc} */
public interface LedgerConfigurationClient {
Flowable<LedgerConfigurationServiceOuterClass.LedgerConfiguration> getLedgerConfiguration();
Flowable<LedgerConfigurationServiceOuterClass.LedgerConfiguration> getLedgerConfiguration(
String accessToken);
}

View File

@ -1,20 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava;
import io.reactivex.Single;
// TODO #15208 remove
/**
* An RxJava version of {@link com.daml.ledger.api.v1.LedgerIdentityServiceGrpc}
*
* @deprecated Ledger identity string is optional for all ledger API requests, since Daml 2.0.0
*/
@Deprecated
public interface LedgerIdentityClient {
Single<String> getLedgerIdentity();
Single<String> getLedgerIdentity(String accessToken);
}

View File

@ -3,21 +3,19 @@
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.ActiveContracts;
import com.daml.ledger.javaapi.data.ContractFilter;
import com.daml.ledger.javaapi.data.GetActiveContractsResponse;
import com.daml.ledger.javaapi.data.TransactionFilter;
import com.daml.ledger.javaapi.data.*;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Set;
/** An RxJava version of {@link com.daml.ledger.api.v1.ActiveContractsServiceGrpc} */
public interface ActiveContractsClient {
public interface StateClient {
Flowable<GetActiveContractsResponse> getActiveContracts(
TransactionFilter filter, boolean verbose);
Flowable<GetActiveContractsResponseV2> getActiveContracts(
TransactionFilterV2 filter, boolean verbose);
Flowable<GetActiveContractsResponse> getActiveContracts(
TransactionFilter filter, boolean verbose, String accessToken);
Flowable<GetActiveContractsResponseV2> getActiveContracts(
TransactionFilterV2 filter, boolean verbose, String accessToken);
/**
* Get active Contracts
@ -45,4 +43,8 @@ public interface ActiveContractsClient {
*/
<Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter, Set<String> parties, boolean verbose, String accessToken);
Single<ParticipantOffsetV2> getLedgerEnd();
Single<ParticipantOffsetV2> getLedgerEnd(String accessToken);
}

View File

@ -1,79 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.*;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Set;
/** An RxJava version of {@link com.daml.ledger.api.v1.TransactionServiceGrpc} */
public interface TransactionsClient {
Flowable<Transaction> getTransactions(
LedgerOffset begin, LedgerOffset end, TransactionFilter filter, boolean verbose);
Flowable<Transaction> getTransactions(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
String accessToken);
Flowable<Transaction> getTransactions(
LedgerOffset begin, TransactionFilter filter, boolean verbose);
Flowable<Transaction> getTransactions(
LedgerOffset begin, TransactionFilter filter, boolean verbose, String accessToken);
Flowable<Transaction> getTransactions(
ContractFilter<?> contractFilter, LedgerOffset begin, Set<String> parties, boolean verbose);
Flowable<Transaction> getTransactions(
ContractFilter<?> contractFilter,
LedgerOffset begin,
Set<String> parties,
boolean verbose,
String accessToken);
Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, LedgerOffset end, TransactionFilter filter, boolean verbose);
Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
String accessToken);
Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, TransactionFilter filter, boolean verbose);
Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, TransactionFilter filter, boolean verbose, String accessToken);
Single<TransactionTree> getTransactionByEventId(String eventId, Set<String> requestingParties);
Single<TransactionTree> getTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken);
Single<TransactionTree> getTransactionById(String transactionId, Set<String> requestingParties);
Single<TransactionTree> getTransactionById(
String transactionId, Set<String> requestingParties, String accessToken);
Single<Transaction> getFlatTransactionByEventId(String eventId, Set<String> requestingParties);
Single<Transaction> getFlatTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken);
Single<Transaction> getFlatTransactionById(String transactionId, Set<String> requestingParties);
Single<Transaction> getFlatTransactionById(
String transactionId, Set<String> requestingParties, String accessToken);
Single<LedgerOffset> getLedgerEnd();
Single<LedgerOffset> getLedgerEnd(String accessToken);
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava;
import com.daml.ledger.javaapi.data.*;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Set;
/** An RxJava version of {@link com.daml.ledger.api.v2.UpdateServiceGrpc} */
public interface UpdateClient {
Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose);
Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
String accessToken);
Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose);
Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose, String accessToken);
Flowable<TransactionV2> getTransactions(
ContractFilter<?> contractFilter,
ParticipantOffsetV2 begin,
Set<String> parties,
boolean verbose);
Flowable<TransactionV2> getTransactions(
ContractFilter<?> contractFilter,
ParticipantOffsetV2 begin,
Set<String> parties,
boolean verbose,
String accessToken);
Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose);
Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
String accessToken);
Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose);
Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose, String accessToken);
Single<TransactionTreeV2> getTransactionTreeByEventId(
String eventId, Set<String> requestingParties);
Single<TransactionTreeV2> getTransactionTreeByEventId(
String eventId, Set<String> requestingParties, String accessToken);
Single<TransactionTreeV2> getTransactionTreeById(
String transactionId, Set<String> requestingParties);
Single<TransactionTreeV2> getTransactionTreeById(
String transactionId, Set<String> requestingParties, String accessToken);
Single<TransactionV2> getTransactionByEventId(String eventId, Set<String> requestingParties);
Single<TransactionV2> getTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken);
Single<TransactionV2> getTransactionById(String transactionId, Set<String> requestingParties);
Single<TransactionV2> getTransactionById(
String transactionId, Set<String> requestingParties, String accessToken);
}

View File

@ -1,96 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v1.ActiveContractsServiceGrpc;
import com.daml.ledger.api.v1.ActiveContractsServiceOuterClass;
import com.daml.ledger.javaapi.data.ActiveContracts;
import com.daml.ledger.javaapi.data.ContractFilter;
import com.daml.ledger.javaapi.data.GetActiveContractsRequest;
import com.daml.ledger.javaapi.data.GetActiveContractsResponse;
import com.daml.ledger.javaapi.data.TransactionFilter;
import com.daml.ledger.rxjava.ActiveContractsClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.NonNull;
public class ActiveContractClientImpl implements ActiveContractsClient {
private final String ledgerId;
private final ActiveContractsServiceGrpc.ActiveContractsServiceStub serviceStub;
private ExecutionSequencerFactory sequencerFactory;
public ActiveContractClientImpl(
String ledgerId,
Channel channel,
ExecutionSequencerFactory sequencerFactory,
Optional<String> accessToken) {
this.ledgerId = ledgerId;
this.sequencerFactory = sequencerFactory;
this.serviceStub =
StubHelper.authenticating(ActiveContractsServiceGrpc.newStub(channel), accessToken);
}
private Flowable<GetActiveContractsResponse> getActiveContracts(
@NonNull TransactionFilter filter, boolean verbose, @NonNull Optional<String> accessToken) {
ActiveContractsServiceOuterClass.GetActiveContractsRequest request =
new GetActiveContractsRequest(ledgerId, filter, verbose).toProto();
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getActiveContracts,
sequencerFactory)
.map(GetActiveContractsResponse::fromProto);
}
@Override
public Flowable<GetActiveContractsResponse> getActiveContracts(
@NonNull TransactionFilter filter, boolean verbose) {
return getActiveContracts(filter, verbose, Optional.empty());
}
@Override
public Flowable<GetActiveContractsResponse> getActiveContracts(
@NonNull TransactionFilter filter, boolean verbose, @NonNull String accessToken) {
return getActiveContracts(filter, verbose, Optional.of(accessToken));
}
private <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter,
Set<String> parties,
boolean verbose,
Optional<String> accessToken) {
TransactionFilter filter = contractFilter.transactionFilter(parties);
Flowable<GetActiveContractsResponse> responses =
getActiveContracts(filter, verbose, accessToken);
return responses.map(
response -> {
List<Ct> activeContracts =
response.getCreatedEvents().stream()
.map(contractFilter::toContract)
.collect(Collectors.toList());
return new ActiveContracts<>(
response.getOffset(), activeContracts, response.getWorkflowId());
});
}
@Override
public <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter, Set<String> parties, boolean verbose) {
return getActiveContracts(contractFilter, parties, verbose, Optional.empty());
}
@Override
public <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter, Set<String> parties, boolean verbose, String accessToken) {
return getActiveContracts(contractFilter, parties, verbose, Optional.of(accessToken));
}
}

View File

@ -6,8 +6,8 @@ package com.daml.ledger.rxjava.grpc;
import static com.daml.ledger.javaapi.data.EventUtils.firstExercisedEvent;
import static com.daml.ledger.javaapi.data.EventUtils.singleCreatedEvent;
import com.daml.ledger.api.v1.CommandServiceGrpc;
import com.daml.ledger.api.v1.CommandServiceOuterClass;
import com.daml.ledger.api.v2.CommandServiceGrpc;
import com.daml.ledger.api.v2.CommandServiceOuterClass;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.javaapi.data.codegen.Created;
import com.daml.ledger.javaapi.data.codegen.Exercised;
@ -22,20 +22,17 @@ import org.checkerframework.checker.nullness.qual.NonNull;
public class CommandClientImpl implements CommandClient {
private final String ledgerId;
private final CommandServiceGrpc.CommandServiceFutureStub serviceStub;
public CommandClientImpl(
@NonNull String ledgerId, @NonNull Channel channel, @NonNull Optional<String> accessToken) {
this.ledgerId = ledgerId;
public CommandClientImpl(@NonNull Channel channel, @NonNull Optional<String> accessToken) {
this.serviceStub =
StubHelper.authenticating(CommandServiceGrpc.newFutureStub(channel), accessToken);
}
@Override
public Single<Empty> submitAndWait(CommandsSubmission submission) {
public Single<Empty> submitAndWait(CommandsSubmissionV2 submission) {
CommandServiceOuterClass.SubmitAndWaitRequest request =
SubmitAndWaitRequest.toProto(this.ledgerId, submission);
SubmitAndWaitRequestV2.toProto(submission);
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, submission.getAccessToken())
@ -43,41 +40,42 @@ public class CommandClientImpl implements CommandClient {
}
@Override
public Single<String> submitAndWaitForTransactionId(CommandsSubmission submission) {
public Single<String> submitAndWaitForTransactionId(CommandsSubmissionV2 submission) {
CommandServiceOuterClass.SubmitAndWaitRequest request =
SubmitAndWaitRequest.toProto(this.ledgerId, submission);
SubmitAndWaitRequestV2.toProto(submission);
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, submission.getAccessToken())
.submitAndWaitForTransactionId(request))
.map(CommandServiceOuterClass.SubmitAndWaitForTransactionIdResponse::getTransactionId);
.submitAndWaitForUpdateId(request))
.map(CommandServiceOuterClass.SubmitAndWaitForUpdateIdResponse::getUpdateId);
}
@Override
public Single<Transaction> submitAndWaitForTransaction(CommandsSubmission submission) {
public Single<TransactionV2> submitAndWaitForTransaction(CommandsSubmissionV2 submission) {
CommandServiceOuterClass.SubmitAndWaitRequest request =
SubmitAndWaitRequest.toProto(this.ledgerId, submission);
SubmitAndWaitRequestV2.toProto(submission);
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, submission.getAccessToken())
.submitAndWaitForTransaction(request))
.map(CommandServiceOuterClass.SubmitAndWaitForTransactionResponse::getTransaction)
.map(Transaction::fromProto);
.map(TransactionV2::fromProto);
}
@Override
public Single<TransactionTree> submitAndWaitForTransactionTree(CommandsSubmission submission) {
public Single<TransactionTreeV2> submitAndWaitForTransactionTree(
CommandsSubmissionV2 submission) {
CommandServiceOuterClass.SubmitAndWaitRequest request =
SubmitAndWaitRequest.toProto(this.ledgerId, submission);
SubmitAndWaitRequestV2.toProto(submission);
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, submission.getAccessToken())
.submitAndWaitForTransactionTree(request))
.map(CommandServiceOuterClass.SubmitAndWaitForTransactionTreeResponse::getTransaction)
.map(TransactionTree::fromProto);
.map(TransactionTreeV2::fromProto);
}
@Override
public <U> Single<U> submitAndWaitForResult(@NonNull UpdateSubmission<U> submission) {
public <U> Single<U> submitAndWaitForResult(@NonNull UpdateSubmissionV2<U> submission) {
return submission
.getUpdate()
.foldUpdate(

View File

@ -4,34 +4,26 @@
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v1.CommandCompletionServiceGrpc;
import com.daml.ledger.api.v1.CommandCompletionServiceOuterClass;
import com.daml.ledger.javaapi.data.CompletionEndResponse;
import com.daml.ledger.javaapi.data.CompletionStreamRequest;
import com.daml.ledger.javaapi.data.CompletionStreamResponse;
import com.daml.ledger.javaapi.data.LedgerOffset;
import com.daml.ledger.api.v2.CommandCompletionServiceGrpc;
import com.daml.ledger.javaapi.data.CompletionStreamRequestV2;
import com.daml.ledger.javaapi.data.CompletionStreamResponseV2;
import com.daml.ledger.javaapi.data.ParticipantOffsetV2;
import com.daml.ledger.rxjava.CommandCompletionClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class CommandCompletionClientImpl implements CommandCompletionClient {
private final String ledgerId;
private final CommandCompletionServiceGrpc.CommandCompletionServiceStub serviceStub;
private final CommandCompletionServiceGrpc.CommandCompletionServiceFutureStub serviceFutureStub;
private final ExecutionSequencerFactory sequencerFactory;
public CommandCompletionClientImpl(
String ledgerId,
Channel channel,
ExecutionSequencerFactory sequencerFactory,
Optional<String> accessToken) {
this.ledgerId = ledgerId;
Channel channel, ExecutionSequencerFactory sequencerFactory, Optional<String> accessToken) {
this.sequencerFactory = sequencerFactory;
this.serviceStub =
StubHelper.authenticating(CommandCompletionServiceGrpc.newStub(channel), accessToken);
@ -39,61 +31,44 @@ public class CommandCompletionClientImpl implements CommandCompletionClient {
StubHelper.authenticating(CommandCompletionServiceGrpc.newFutureStub(channel), accessToken);
}
private Flowable<CompletionStreamResponse> completionStream(
CompletionStreamRequest request, Optional<String> accessToken) {
private Flowable<CompletionStreamResponseV2> completionStream(
CompletionStreamRequestV2 request, Optional<String> accessToken) {
return ClientPublisherFlowable.create(
request.toProto(),
StubHelper.authenticating(serviceStub, accessToken)::completionStream,
sequencerFactory)
.map(CompletionStreamResponse::fromProto);
.map(CompletionStreamResponseV2::fromProto);
}
@Override
public Flowable<CompletionStreamResponse> completionStream(
String applicationId, LedgerOffset offset, Set<String> parties) {
public Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, ParticipantOffsetV2 offset, List<String> parties) {
return completionStream(
new CompletionStreamRequest(ledgerId, applicationId, parties, offset), Optional.empty());
new CompletionStreamRequestV2(applicationId, parties, offset), Optional.empty());
}
@Override
public Flowable<CompletionStreamResponse> completionStream(
String applicationId, LedgerOffset offset, Set<String> parties, String accessToken) {
public Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, ParticipantOffsetV2 offset, List<String> parties, String accessToken) {
return completionStream(
new CompletionStreamRequest(ledgerId, applicationId, parties, offset),
new CompletionStreamRequestV2(applicationId, parties, offset), Optional.of(accessToken));
}
@Override
public Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, List<String> parties) {
return completionStream(
new CompletionStreamRequestV2(
applicationId, parties, ParticipantOffsetV2.ParticipantBegin.getInstance()),
Optional.empty());
}
@Override
public Flowable<CompletionStreamResponseV2> completionStream(
String applicationId, List<String> parties, String accessToken) {
return completionStream(
new CompletionStreamRequestV2(
applicationId, parties, ParticipantOffsetV2.ParticipantBegin.getInstance()),
Optional.of(accessToken));
}
@Override
public Flowable<CompletionStreamResponse> completionStream(
String applicationId, Set<String> parties) {
return completionStream(
new CompletionStreamRequest(ledgerId, applicationId, parties), Optional.empty());
}
@Override
public Flowable<CompletionStreamResponse> completionStream(
String applicationId, Set<String> parties, String accessToken) {
return completionStream(
new CompletionStreamRequest(ledgerId, applicationId, parties), Optional.of(accessToken));
}
private Single<CompletionEndResponse> completionEnd(Optional<String> accessToken) {
CommandCompletionServiceOuterClass.CompletionEndRequest request =
CommandCompletionServiceOuterClass.CompletionEndRequest.newBuilder()
.setLedgerId(ledgerId)
.build();
return Single.fromFuture(
StubHelper.authenticating(serviceFutureStub, accessToken).completionEnd(request))
.map(CompletionEndResponse::fromProto);
}
@Override
public Single<CompletionEndResponse> completionEnd() {
return completionEnd(Optional.empty());
}
@Override
public Single<CompletionEndResponse> completionEnd(String accessToken) {
return completionEnd(Optional.of(accessToken));
}
}

View File

@ -5,13 +5,13 @@ package com.daml.ledger.rxjava.grpc;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.daml.ledger.api.v1.CommandSubmissionServiceGrpc;
import com.daml.ledger.api.v1.CommandSubmissionServiceOuterClass;
import com.daml.ledger.javaapi.data.CommandsSubmission;
import com.daml.ledger.javaapi.data.SubmitRequest;
import com.daml.ledger.api.v2.CommandSubmissionServiceGrpc;
import com.daml.ledger.api.v2.CommandSubmissionServiceOuterClass;
import com.daml.ledger.api.v2.CommandSubmissionServiceOuterClass.SubmitResponse;
import com.daml.ledger.javaapi.data.CommandsSubmissionV2;
import com.daml.ledger.javaapi.data.SubmitRequestV2;
import com.daml.ledger.rxjava.CommandSubmissionClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.google.protobuf.Empty;
import io.grpc.Channel;
import io.reactivex.Single;
import java.time.Duration;
@ -20,25 +20,19 @@ import org.checkerframework.checker.nullness.qual.NonNull;
public class CommandSubmissionClientImpl implements CommandSubmissionClient {
private final String ledgerId;
private final CommandSubmissionServiceGrpc.CommandSubmissionServiceFutureStub serviceStub;
private final Optional<Duration> timeout;
public CommandSubmissionClientImpl(
@NonNull String ledgerId,
@NonNull Channel channel,
Optional<String> accessToken,
Optional<Duration> timeout) {
this.ledgerId = ledgerId;
@NonNull Channel channel, Optional<String> accessToken, Optional<Duration> timeout) {
this.timeout = timeout;
this.serviceStub =
StubHelper.authenticating(CommandSubmissionServiceGrpc.newFutureStub(channel), accessToken);
}
@Override
public Single<Empty> submit(CommandsSubmission submission) {
CommandSubmissionServiceOuterClass.SubmitRequest request =
SubmitRequest.toProto(ledgerId, submission);
public Single<SubmitResponse> submit(CommandsSubmissionV2 submission) {
CommandSubmissionServiceOuterClass.SubmitRequest request = SubmitRequestV2.toProto(submission);
CommandSubmissionServiceGrpc.CommandSubmissionServiceFutureStub stubWithTimeout =
this.timeout
.map(t -> this.serviceStub.withDeadlineAfter(t.toMillis(), MILLISECONDS))

View File

@ -3,12 +3,9 @@
package com.daml.ledger.rxjava.grpc;
import com.daml.ledger.api.v1.EventQueryServiceGrpc;
import com.daml.ledger.api.v1.EventQueryServiceOuterClass;
import com.daml.ledger.javaapi.data.GetEventsByContractIdResponse;
import com.daml.ledger.javaapi.data.GetEventsByContractKeyResponse;
import com.daml.ledger.javaapi.data.Identifier;
import com.daml.ledger.javaapi.data.Value;
import com.daml.ledger.api.v1.EventQueryServiceOuterClass.GetEventsByContractIdRequest;
import com.daml.ledger.api.v2.EventQueryServiceGrpc;
import com.daml.ledger.javaapi.data.GetEventsByContractIdResponseV2;
import com.daml.ledger.rxjava.EventQueryClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import io.grpc.Channel;
@ -25,68 +22,27 @@ public class EventQueryClientImpl implements EventQueryClient {
StubHelper.authenticating(EventQueryServiceGrpc.newFutureStub(channel), accessToken);
}
private Single<GetEventsByContractIdResponse> getEventsByContractId(
private Single<GetEventsByContractIdResponseV2> getEventsByContractId(
String contractId, Set<String> requestingParties, Optional<String> accessToken) {
EventQueryServiceOuterClass.GetEventsByContractIdRequest request =
EventQueryServiceOuterClass.GetEventsByContractIdRequest.newBuilder()
GetEventsByContractIdRequest request =
GetEventsByContractIdRequest.newBuilder()
.setContractId(contractId)
.addAllRequestingParties(requestingParties)
.build();
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, accessToken).getEventsByContractId(request))
.map(GetEventsByContractIdResponse::fromProto);
.map(GetEventsByContractIdResponseV2::fromProto);
}
@Override
public Single<GetEventsByContractIdResponse> getEventsByContractId(
public Single<GetEventsByContractIdResponseV2> getEventsByContractId(
String contractId, Set<String> requestingParties) {
return getEventsByContractId(contractId, requestingParties, Optional.empty());
}
@Override
public Single<GetEventsByContractIdResponse> getEventsByContractId(
public Single<GetEventsByContractIdResponseV2> getEventsByContractId(
String contractId, Set<String> requestingParties, String accessToken) {
return getEventsByContractId(contractId, requestingParties, Optional.of(accessToken));
}
private Single<GetEventsByContractKeyResponse> getEventsByContractKey(
Value contractKey,
Identifier templateId,
Set<String> requestingParties,
String continuationToken,
Optional<String> accessToken) {
EventQueryServiceOuterClass.GetEventsByContractKeyRequest request =
EventQueryServiceOuterClass.GetEventsByContractKeyRequest.newBuilder()
.setContractKey(contractKey.toProto())
.setTemplateId(templateId.toProto())
.setContinuationToken(continuationToken)
.addAllRequestingParties(requestingParties)
.build();
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, accessToken)
.getEventsByContractKey(request))
.map(GetEventsByContractKeyResponse::fromProto);
}
@Override
public Single<GetEventsByContractKeyResponse> getEventsByContractKey(
Value contractKey,
Identifier templateId,
Set<String> requestingParties,
String continuationToken) {
return getEventsByContractKey(
contractKey, templateId, requestingParties, continuationToken, Optional.empty());
}
@Override
public Single<GetEventsByContractKeyResponse> getEventsByContractKey(
Value contractKey,
Identifier templateId,
Set<String> requestingParties,
String continuationToken,
String accessToken) {
return getEventsByContractKey(
contractKey, templateId, requestingParties, continuationToken, Optional.of(accessToken));
}
}

View File

@ -1,59 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v1.LedgerConfigurationServiceGrpc;
import com.daml.ledger.api.v1.LedgerConfigurationServiceOuterClass;
import com.daml.ledger.rxjava.LedgerConfigurationClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import java.util.Optional;
public class LedgerConfigurationClientImpl implements LedgerConfigurationClient {
private final String ledgerId;
private final LedgerConfigurationServiceGrpc.LedgerConfigurationServiceStub serviceStub;
private final ExecutionSequencerFactory sequencerFactory;
public LedgerConfigurationClientImpl(
String ledgerId,
Channel channel,
ExecutionSequencerFactory sequencerFactory,
Optional<String> accessToken) {
this.ledgerId = ledgerId;
this.sequencerFactory = sequencerFactory;
this.serviceStub =
StubHelper.authenticating(LedgerConfigurationServiceGrpc.newStub(channel), accessToken);
}
private Flowable<LedgerConfigurationServiceOuterClass.LedgerConfiguration> getLedgerConfiguration(
Optional<String> accessToken) {
LedgerConfigurationServiceOuterClass.GetLedgerConfigurationRequest request =
LedgerConfigurationServiceOuterClass.GetLedgerConfigurationRequest.newBuilder()
.setLedgerId(ledgerId)
.build();
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getLedgerConfiguration,
sequencerFactory)
.map(
LedgerConfigurationServiceOuterClass.GetLedgerConfigurationResponse
::getLedgerConfiguration);
}
@Override
public Flowable<LedgerConfigurationServiceOuterClass.LedgerConfiguration>
getLedgerConfiguration() {
return getLedgerConfiguration(Optional.empty());
}
@Override
public Flowable<LedgerConfigurationServiceOuterClass.LedgerConfiguration> getLedgerConfiguration(
String accessToken) {
return getLedgerConfiguration(Optional.of(accessToken));
}
}

View File

@ -1,62 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.daml.ledger.api.v1.LedgerIdentityServiceGrpc;
import com.daml.ledger.api.v1.LedgerIdentityServiceOuterClass;
import com.daml.ledger.rxjava.LedgerIdentityClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import io.grpc.Channel;
import io.reactivex.Single;
import java.time.Duration;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.NonNull;
/** @deprecated ledger identity string is optional for all Ledger API requests since Daml 2.0.0 */
@Deprecated
public class LedgerIdentityClientImpl implements LedgerIdentityClient {
private LedgerIdentityServiceGrpc.LedgerIdentityServiceFutureStub serviceStub;
private final Optional<Duration> timeout;
/**
* @deprecated Pass a timeout or {@code Optional.empty()} as the third argument, since Daml 2.4.0
*/
@Deprecated
public LedgerIdentityClientImpl(Channel channel, Optional<String> accessToken) {
this(channel, accessToken, Optional.empty());
}
public LedgerIdentityClientImpl(
Channel channel, Optional<String> accessToken, Optional<Duration> timeout) {
this.serviceStub =
StubHelper.authenticating(LedgerIdentityServiceGrpc.newFutureStub(channel), accessToken);
this.timeout = timeout;
}
private Single<String> getLedgerIdentity(@NonNull Optional<String> accessToken) {
this.serviceStub =
this.timeout
.map(t -> this.serviceStub.withDeadlineAfter(t.toMillis(), MILLISECONDS))
.orElse(this.serviceStub);
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, accessToken)
.getLedgerIdentity(
LedgerIdentityServiceOuterClass.GetLedgerIdentityRequest.getDefaultInstance()))
.map(LedgerIdentityServiceOuterClass.GetLedgerIdentityResponse::getLedgerId);
}
@Override
public Single<String> getLedgerIdentity() {
return getLedgerIdentity(Optional.empty());
}
@Override
public Single<String> getLedgerIdentity(@NonNull String accessToken) {
return getLedgerIdentity(Optional.of(accessToken));
}
}

View File

@ -3,8 +3,9 @@
package com.daml.ledger.rxjava.grpc;
import com.daml.ledger.api.v1.PackageServiceGrpc;
import com.daml.ledger.api.v1.PackageServiceOuterClass;
import com.daml.ledger.api.v1.PackageServiceOuterClass.ListPackagesResponse;
import com.daml.ledger.api.v2.PackageServiceGrpc;
import com.daml.ledger.api.v2.PackageServiceOuterClass;
import com.daml.ledger.javaapi.data.GetPackageResponse;
import com.daml.ledger.javaapi.data.GetPackageStatusResponse;
import com.daml.ledger.rxjava.PackageClient;
@ -16,20 +17,18 @@ import java.util.Optional;
public class PackageClientImpl implements PackageClient {
private final String ledgerId;
private final PackageServiceGrpc.PackageServiceFutureStub serviceStub;
public PackageClientImpl(String ledgerId, Channel channel, Optional<String> accessToken) {
this.ledgerId = ledgerId;
public PackageClientImpl(Channel channel, Optional<String> accessToken) {
serviceStub = StubHelper.authenticating(PackageServiceGrpc.newFutureStub(channel), accessToken);
}
private Flowable<String> listPackages(Optional<String> accessToken) {
PackageServiceOuterClass.ListPackagesRequest request =
PackageServiceOuterClass.ListPackagesRequest.newBuilder().setLedgerId(ledgerId).build();
PackageServiceOuterClass.ListPackagesRequest.newBuilder().build();
return Flowable.fromFuture(
StubHelper.authenticating(this.serviceStub, accessToken).listPackages(request))
.concatMapIterable(PackageServiceOuterClass.ListPackagesResponse::getPackageIdsList);
.concatMapIterable(ListPackagesResponse::getPackageIdsList);
}
@Override
@ -44,10 +43,7 @@ public class PackageClientImpl implements PackageClient {
private Single<GetPackageResponse> getPackage(String packageId, Optional<String> accessToken) {
PackageServiceOuterClass.GetPackageRequest request =
PackageServiceOuterClass.GetPackageRequest.newBuilder()
.setLedgerId(ledgerId)
.setPackageId(packageId)
.build();
PackageServiceOuterClass.GetPackageRequest.newBuilder().setPackageId(packageId).build();
return Single.fromFuture(
StubHelper.authenticating(this.serviceStub, accessToken).getPackage(request))
.map(GetPackageResponse::fromProto);
@ -67,7 +63,6 @@ public class PackageClientImpl implements PackageClient {
String packageId, Optional<String> accessToken) {
PackageServiceOuterClass.GetPackageStatusRequest request =
PackageServiceOuterClass.GetPackageStatusRequest.newBuilder()
.setLedgerId(ledgerId)
.setPackageId(packageId)
.build();
return Single.fromFuture(

View File

@ -0,0 +1,109 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v2.StateServiceGrpc;
import com.daml.ledger.api.v2.StateServiceOuterClass;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.rxjava.StateClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.NonNull;
public class StateClientImpl implements StateClient {
private final StateServiceGrpc.StateServiceStub serviceStub;
private final StateServiceGrpc.StateServiceFutureStub serviceFutureStub;
private ExecutionSequencerFactory sequencerFactory;
public StateClientImpl(
Channel channel, ExecutionSequencerFactory sequencerFactory, Optional<String> accessToken) {
this.sequencerFactory = sequencerFactory;
this.serviceStub = StubHelper.authenticating(StateServiceGrpc.newStub(channel), accessToken);
this.serviceFutureStub =
StubHelper.authenticating(StateServiceGrpc.newFutureStub(channel), accessToken);
}
private Flowable<GetActiveContractsResponseV2> getActiveContracts(
@NonNull TransactionFilterV2 filter, boolean verbose, @NonNull Optional<String> accessToken) {
StateServiceOuterClass.GetActiveContractsRequest request =
new GetActiveContractsRequestV2(filter, verbose, "").toProto();
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getActiveContracts,
sequencerFactory)
.map(GetActiveContractsResponseV2::fromProto);
}
@Override
public Flowable<GetActiveContractsResponseV2> getActiveContracts(
@NonNull TransactionFilterV2 filter, boolean verbose) {
return getActiveContracts(filter, verbose, Optional.empty());
}
@Override
public Flowable<GetActiveContractsResponseV2> getActiveContracts(
@NonNull TransactionFilterV2 filter, boolean verbose, @NonNull String accessToken) {
return getActiveContracts(filter, verbose, Optional.of(accessToken));
}
private <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter,
Set<String> parties,
boolean verbose,
Optional<String> accessToken) {
TransactionFilterV2 filter = contractFilter.transactionFilterV2(parties);
Flowable<GetActiveContractsResponseV2> responses =
getActiveContracts(filter, verbose, accessToken);
return responses.map(
response -> {
List<Ct> activeContracts =
response.getContractEntry().stream()
.map(ce -> contractFilter.toContract(ce.getCreatedEvent()))
.collect(Collectors.toList());
return new ActiveContracts<>(
response.getOffset(), activeContracts, response.getWorkflowId());
});
}
@Override
public <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter, Set<String> parties, boolean verbose) {
return getActiveContracts(contractFilter, parties, verbose, Optional.empty());
}
@Override
public <Ct> Flowable<ActiveContracts<Ct>> getActiveContracts(
ContractFilter<Ct> contractFilter, Set<String> parties, boolean verbose, String accessToken) {
return getActiveContracts(contractFilter, parties, verbose, Optional.of(accessToken));
}
private Single<ParticipantOffsetV2> getLedgerEnd(Optional<String> accessToken) {
StateServiceOuterClass.GetLedgerEndRequest request =
StateServiceOuterClass.GetLedgerEndRequest.newBuilder().build();
return Single.fromFuture(
StubHelper.authenticating(this.serviceFutureStub, accessToken).getLedgerEnd(request))
.map(GetLedgerEndResponseV2::fromProto)
.map(GetLedgerEndResponseV2::getOffset);
}
@Override
public Single<ParticipantOffsetV2> getLedgerEnd() {
return getLedgerEnd(Optional.empty());
}
@Override
public Single<ParticipantOffsetV2> getLedgerEnd(String accessToken) {
return getLedgerEnd(Optional.of(accessToken));
}
}

View File

@ -4,8 +4,8 @@
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v1.testing.TimeServiceGrpc;
import com.daml.ledger.api.v1.testing.TimeServiceOuterClass;
import com.daml.ledger.api.v2.testing.TimeServiceGrpc;
import com.daml.ledger.api.v2.testing.TimeServiceOuterClass;
import com.daml.ledger.rxjava.TimeClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
@ -19,17 +19,12 @@ import java.util.Optional;
public final class TimeClientImpl implements TimeClient {
private final String ledgerId;
private final TimeServiceGrpc.TimeServiceFutureStub serviceFutureStub;
private final TimeServiceGrpc.TimeServiceStub serviceStub;
private final ExecutionSequencerFactory sequencerFactory;
public TimeClientImpl(
String ledgerId,
Channel channel,
ExecutionSequencerFactory sequencerFactory,
Optional<String> accessToken) {
this.ledgerId = ledgerId;
Channel channel, ExecutionSequencerFactory sequencerFactory, Optional<String> accessToken) {
this.sequencerFactory = sequencerFactory;
this.serviceFutureStub =
StubHelper.authenticating(TimeServiceGrpc.newFutureStub(channel), accessToken);
@ -43,7 +38,6 @@ public final class TimeClientImpl implements TimeClient {
}
TimeServiceOuterClass.SetTimeRequest request =
TimeServiceOuterClass.SetTimeRequest.newBuilder()
.setLedgerId(this.ledgerId)
.setCurrentTime(
Timestamp.newBuilder()
.setSeconds(currentTime.getEpochSecond())
@ -70,7 +64,7 @@ public final class TimeClientImpl implements TimeClient {
private Flowable<Instant> getTime(Optional<String> accessToken) {
TimeServiceOuterClass.GetTimeRequest request =
TimeServiceOuterClass.GetTimeRequest.newBuilder().setLedgerId(this.ledgerId).build();
TimeServiceOuterClass.GetTimeRequest.newBuilder().build();
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getTime,

View File

@ -1,306 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v1.TransactionServiceGrpc;
import com.daml.ledger.api.v1.TransactionServiceOuterClass;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.rxjava.TransactionsClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Future;
public final class TransactionClientImpl implements TransactionsClient {
private final String ledgerId;
private final TransactionServiceGrpc.TransactionServiceStub serviceStub;
private final TransactionServiceGrpc.TransactionServiceFutureStub serviceFutureStub;
private final ExecutionSequencerFactory sequencerFactory;
public TransactionClientImpl(
String ledgerId,
Channel channel,
ExecutionSequencerFactory sequencerFactory,
Optional<String> accessToken) {
this.ledgerId = ledgerId;
this.sequencerFactory = sequencerFactory;
this.serviceStub =
StubHelper.authenticating(TransactionServiceGrpc.newStub(channel), accessToken);
this.serviceFutureStub =
StubHelper.authenticating(TransactionServiceGrpc.newFutureStub(channel), accessToken);
}
private Flowable<Transaction> extractTransactions(
TransactionServiceOuterClass.GetTransactionsRequest request, Optional<String> accessToken) {
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getTransactions,
sequencerFactory)
.map(GetTransactionsResponse::fromProto)
.concatMapIterable(GetTransactionsResponse::getTransactions);
}
private Flowable<Transaction> getTransactions(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionsRequest request =
new GetTransactionsRequest(ledgerId, begin, end, filter, verbose).toProto();
return extractTransactions(request, accessToken);
}
@Override
public Flowable<Transaction> getTransactions(
LedgerOffset begin, LedgerOffset end, TransactionFilter filter, boolean verbose) {
return getTransactions(begin, end, filter, verbose, Optional.empty());
}
@Override
public Flowable<Transaction> getTransactions(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
String accessToken) {
return getTransactions(begin, end, filter, verbose, Optional.of(accessToken));
}
private Flowable<Transaction> getTransactions(
LedgerOffset begin, TransactionFilter filter, boolean verbose, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionsRequest request =
new GetTransactionsRequest(ledgerId, begin, filter, verbose).toProto();
return extractTransactions(request, accessToken);
}
@Override
public Flowable<Transaction> getTransactions(
LedgerOffset begin, TransactionFilter filter, boolean verbose) {
return getTransactions(begin, filter, verbose, Optional.empty());
}
@Override
public Flowable<Transaction> getTransactions(
LedgerOffset begin, TransactionFilter filter, boolean verbose, String accessToken) {
return getTransactions(begin, filter, verbose, Optional.of(accessToken));
}
private Flowable<Transaction> getTransactions(
ContractFilter<?> contractFilter,
LedgerOffset begin,
Set<String> parties,
boolean verbose,
Optional<String> accessToken) {
TransactionFilter filter = contractFilter.transactionFilter(parties);
return getTransactions(begin, filter, verbose, accessToken);
}
public Flowable<Transaction> getTransactions(
ContractFilter<?> contractFilter,
LedgerOffset begin,
Set<String> parties,
boolean verbose,
String accessToken) {
return getTransactions(contractFilter, begin, parties, verbose, Optional.of(accessToken));
}
public Flowable<Transaction> getTransactions(
ContractFilter<?> contractFilter, LedgerOffset begin, Set<String> parties, boolean verbose) {
return getTransactions(contractFilter, begin, parties, verbose, Optional.empty());
}
private Flowable<TransactionTree> extractTransactionTrees(
TransactionServiceOuterClass.GetTransactionsRequest request, Optional<String> accessToken) {
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getTransactionTrees,
sequencerFactory)
.map(GetTransactionTreesResponse::fromProto)
.concatMapIterable(GetTransactionTreesResponse::getTransactions);
}
private Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, TransactionFilter filter, boolean verbose, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionsRequest request =
new GetTransactionsRequest(ledgerId, begin, filter, verbose).toProto();
return extractTransactionTrees(request, accessToken);
}
@Override
public Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, TransactionFilter filter, boolean verbose) {
return getTransactionsTrees(begin, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, TransactionFilter filter, boolean verbose, String accessToken) {
return getTransactionsTrees(begin, filter, verbose, Optional.of(accessToken));
}
private Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionsRequest request =
new GetTransactionsRequest(ledgerId, begin, end, filter, verbose).toProto();
return extractTransactionTrees(request, accessToken);
}
@Override
public Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin, LedgerOffset end, TransactionFilter filter, boolean verbose) {
return getTransactionsTrees(begin, end, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionTree> getTransactionsTrees(
LedgerOffset begin,
LedgerOffset end,
TransactionFilter filter,
boolean verbose,
String accessToken) {
return getTransactionsTrees(begin, end, filter, verbose, Optional.of(accessToken));
}
private Single<TransactionTree> extractTransactionTree(
Future<TransactionServiceOuterClass.GetTransactionResponse> future) {
return Single.fromFuture(future)
.map(GetTransactionResponse::fromProto)
.map(GetTransactionResponse::getTransaction);
}
private Single<TransactionTree> getTransactionByEventId(
String eventId, Set<String> requestingParties, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionByEventIdRequest request =
TransactionServiceOuterClass.GetTransactionByEventIdRequest.newBuilder()
.setLedgerId(ledgerId)
.setEventId(eventId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransactionTree(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getTransactionByEventId(request));
}
@Override
public Single<TransactionTree> getTransactionByEventId(
String eventId, Set<String> requestingParties) {
return getTransactionByEventId(eventId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionTree> getTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken) {
return getTransactionByEventId(eventId, requestingParties, Optional.of(accessToken));
}
private Single<TransactionTree> getTransactionById(
String transactionId, Set<String> requestingParties, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionByIdRequest request =
TransactionServiceOuterClass.GetTransactionByIdRequest.newBuilder()
.setLedgerId(ledgerId)
.setTransactionId(transactionId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransactionTree(
StubHelper.authenticating(this.serviceFutureStub, accessToken).getTransactionById(request));
}
@Override
public Single<TransactionTree> getTransactionById(
String transactionId, Set<String> requestingParties) {
return getTransactionById(transactionId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionTree> getTransactionById(
String transactionId, Set<String> requestingParties, String accessToken) {
return getTransactionById(transactionId, requestingParties, Optional.of(accessToken));
}
private Single<Transaction> extractTransaction(
Future<TransactionServiceOuterClass.GetFlatTransactionResponse> future) {
return Single.fromFuture(future)
.map(GetFlatTransactionResponse::fromProto)
.map(GetFlatTransactionResponse::getTransaction);
}
private Single<Transaction> getFlatTransactionByEventId(
String eventId, Set<String> requestingParties, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionByEventIdRequest request =
TransactionServiceOuterClass.GetTransactionByEventIdRequest.newBuilder()
.setLedgerId(ledgerId)
.setEventId(eventId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransaction(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getFlatTransactionByEventId(request));
}
@Override
public Single<Transaction> getFlatTransactionByEventId(
String eventId, Set<String> requestingParties) {
return getFlatTransactionByEventId(eventId, requestingParties, Optional.empty());
}
@Override
public Single<Transaction> getFlatTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken) {
return getFlatTransactionByEventId(eventId, requestingParties, Optional.of(accessToken));
}
private Single<Transaction> getFlatTransactionById(
String transactionId, Set<String> requestingParties, Optional<String> accessToken) {
TransactionServiceOuterClass.GetTransactionByIdRequest request =
TransactionServiceOuterClass.GetTransactionByIdRequest.newBuilder()
.setLedgerId(ledgerId)
.setTransactionId(transactionId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransaction(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getFlatTransactionById(request));
}
@Override
public Single<Transaction> getFlatTransactionById(
String transactionId, Set<String> requestingParties) {
return getFlatTransactionById(transactionId, requestingParties, Optional.empty());
}
@Override
public Single<Transaction> getFlatTransactionById(
String transactionId, Set<String> requestingParties, String accessToken) {
return getFlatTransactionById(transactionId, requestingParties, Optional.of(accessToken));
}
private Single<LedgerOffset> getLedgerEnd(Optional<String> accessToken) {
TransactionServiceOuterClass.GetLedgerEndRequest request =
TransactionServiceOuterClass.GetLedgerEndRequest.newBuilder().setLedgerId(ledgerId).build();
return Single.fromFuture(
StubHelper.authenticating(this.serviceFutureStub, accessToken).getLedgerEnd(request))
.map(GetLedgerEndResponse::fromProto)
.map(GetLedgerEndResponse::getOffset);
}
@Override
public Single<LedgerOffset> getLedgerEnd() {
return getLedgerEnd(Optional.empty());
}
@Override
public Single<LedgerOffset> getLedgerEnd(String accessToken) {
return getLedgerEnd(Optional.of(accessToken));
}
}

View File

@ -0,0 +1,303 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc;
import com.daml.grpc.adapter.ExecutionSequencerFactory;
import com.daml.ledger.api.v2.UpdateServiceGrpc;
import com.daml.ledger.api.v2.UpdateServiceOuterClass;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.rxjava.UpdateClient;
import com.daml.ledger.rxjava.grpc.helpers.StubHelper;
import com.daml.ledger.rxjava.util.ClientPublisherFlowable;
import io.grpc.Channel;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Future;
public final class UpdateClientImpl implements UpdateClient {
private final UpdateServiceGrpc.UpdateServiceStub serviceStub;
private final UpdateServiceGrpc.UpdateServiceFutureStub serviceFutureStub;
private final ExecutionSequencerFactory sequencerFactory;
public UpdateClientImpl(
Channel channel, ExecutionSequencerFactory sequencerFactory, Optional<String> accessToken) {
this.sequencerFactory = sequencerFactory;
this.serviceStub = StubHelper.authenticating(UpdateServiceGrpc.newStub(channel), accessToken);
this.serviceFutureStub =
StubHelper.authenticating(UpdateServiceGrpc.newFutureStub(channel), accessToken);
}
private static <T> Iterable<T> toIterable(Optional<T> o) {
return o.map(Collections::singleton).orElseGet(Collections::emptySet);
}
private Flowable<TransactionV2> extractTransactions(
UpdateServiceOuterClass.GetUpdatesRequest request, Optional<String> accessToken) {
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getUpdates,
sequencerFactory)
.map(GetUpdatesResponseV2::fromProto)
.map(GetUpdatesResponseV2::getTransaction)
.concatMapIterable(UpdateClientImpl::toIterable);
}
private Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
Optional<String> accessToken) {
UpdateServiceOuterClass.GetUpdatesRequest request =
new GetUpdatesRequestV2(begin, end, filter, verbose).toProto();
return extractTransactions(request, accessToken);
}
@Override
public Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose) {
return getTransactions(begin, end, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
String accessToken) {
return getTransactions(begin, end, filter, verbose, Optional.of(accessToken));
}
private Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin,
TransactionFilterV2 filter,
boolean verbose,
Optional<String> accessToken) {
UpdateServiceOuterClass.GetUpdatesRequest request =
new GetUpdatesRequestV2(
begin, ParticipantOffsetV2.ParticipantEnd.getInstance(), filter, verbose)
.toProto();
return extractTransactions(request, accessToken);
}
@Override
public Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose) {
return getTransactions(begin, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionV2> getTransactions(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose, String accessToken) {
return getTransactions(begin, filter, verbose, Optional.of(accessToken));
}
private Flowable<TransactionV2> getTransactions(
ContractFilter<?> contractFilter,
ParticipantOffsetV2 begin,
Set<String> parties,
boolean verbose,
Optional<String> accessToken) {
TransactionFilterV2 filter = contractFilter.transactionFilterV2(parties);
return getTransactions(begin, filter, verbose, accessToken);
}
public Flowable<TransactionV2> getTransactions(
ContractFilter<?> contractFilter,
ParticipantOffsetV2 begin,
Set<String> parties,
boolean verbose,
String accessToken) {
return getTransactions(contractFilter, begin, parties, verbose, Optional.of(accessToken));
}
public Flowable<TransactionV2> getTransactions(
ContractFilter<?> contractFilter,
ParticipantOffsetV2 begin,
Set<String> parties,
boolean verbose) {
return getTransactions(contractFilter, begin, parties, verbose, Optional.empty());
}
private Flowable<TransactionTreeV2> extractTransactionTrees(
UpdateServiceOuterClass.GetUpdatesRequest request, Optional<String> accessToken) {
return ClientPublisherFlowable.create(
request,
StubHelper.authenticating(this.serviceStub, accessToken)::getUpdateTrees,
sequencerFactory)
.map(GetUpdateTreesResponseV2::fromProto)
.map(GetUpdateTreesResponseV2::getTransactionTree)
.concatMapIterable(UpdateClientImpl::toIterable);
}
private Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
TransactionFilterV2 filter,
boolean verbose,
Optional<String> accessToken) {
UpdateServiceOuterClass.GetUpdatesRequest request =
new GetUpdatesRequestV2(
begin, ParticipantOffsetV2.ParticipantEnd.getInstance(), filter, verbose)
.toProto();
return extractTransactionTrees(request, accessToken);
}
@Override
public Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose) {
return getTransactionsTrees(begin, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin, TransactionFilterV2 filter, boolean verbose, String accessToken) {
return getTransactionsTrees(begin, filter, verbose, Optional.of(accessToken));
}
private Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
Optional<String> accessToken) {
UpdateServiceOuterClass.GetUpdatesRequest request =
new GetUpdatesRequestV2(begin, end, filter, verbose).toProto();
return extractTransactionTrees(request, accessToken);
}
@Override
public Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose) {
return getTransactionsTrees(begin, end, filter, verbose, Optional.empty());
}
@Override
public Flowable<TransactionTreeV2> getTransactionsTrees(
ParticipantOffsetV2 begin,
ParticipantOffsetV2 end,
TransactionFilterV2 filter,
boolean verbose,
String accessToken) {
return getTransactionsTrees(begin, end, filter, verbose, Optional.of(accessToken));
}
private Single<TransactionTreeV2> extractTransactionTree(
Future<UpdateServiceOuterClass.GetTransactionTreeResponse> future) {
return Single.fromFuture(future)
.map(GetTransactionTreeResponseV2::fromProto)
.map(GetTransactionTreeResponseV2::getTransactionTree);
}
private Single<TransactionTreeV2> getTransactionTreeByEventId(
String eventId, Set<String> requestingParties, Optional<String> accessToken) {
UpdateServiceOuterClass.GetTransactionByEventIdRequest request =
UpdateServiceOuterClass.GetTransactionByEventIdRequest.newBuilder()
.setEventId(eventId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransactionTree(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getTransactionTreeByEventId(request));
}
@Override
public Single<TransactionTreeV2> getTransactionTreeByEventId(
String eventId, Set<String> requestingParties) {
return getTransactionTreeByEventId(eventId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionTreeV2> getTransactionTreeByEventId(
String eventId, Set<String> requestingParties, String accessToken) {
return getTransactionTreeByEventId(eventId, requestingParties, Optional.of(accessToken));
}
private Single<TransactionTreeV2> getTransactionTreeById(
String transactionId, Set<String> requestingParties, Optional<String> accessToken) {
UpdateServiceOuterClass.GetTransactionByIdRequest request =
UpdateServiceOuterClass.GetTransactionByIdRequest.newBuilder()
.setUpdateId(transactionId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransactionTree(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getTransactionTreeById(request));
}
@Override
public Single<TransactionTreeV2> getTransactionTreeById(
String transactionId, Set<String> requestingParties) {
return getTransactionTreeById(transactionId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionTreeV2> getTransactionTreeById(
String transactionId, Set<String> requestingParties, String accessToken) {
return getTransactionTreeById(transactionId, requestingParties, Optional.of(accessToken));
}
private Single<TransactionV2> extractTransaction(
Future<UpdateServiceOuterClass.GetTransactionResponse> future) {
return Single.fromFuture(future)
.map(GetTransactionResponseV2::fromProto)
.map(GetTransactionResponseV2::getTransaction);
}
private Single<TransactionV2> getTransactionByEventId(
String eventId, Set<String> requestingParties, Optional<String> accessToken) {
UpdateServiceOuterClass.GetTransactionByEventIdRequest request =
UpdateServiceOuterClass.GetTransactionByEventIdRequest.newBuilder()
.setEventId(eventId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransaction(
StubHelper.authenticating(this.serviceFutureStub, accessToken)
.getTransactionByEventId(request));
}
@Override
public Single<TransactionV2> getTransactionByEventId(
String eventId, Set<String> requestingParties) {
return getTransactionByEventId(eventId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionV2> getTransactionByEventId(
String eventId, Set<String> requestingParties, String accessToken) {
return getTransactionByEventId(eventId, requestingParties, Optional.of(accessToken));
}
private Single<TransactionV2> getTransactionById(
String transactionId, Set<String> requestingParties, Optional<String> accessToken) {
UpdateServiceOuterClass.GetTransactionByIdRequest request =
UpdateServiceOuterClass.GetTransactionByIdRequest.newBuilder()
.setUpdateId(transactionId)
.addAllRequestingParties(requestingParties)
.build();
return extractTransaction(
StubHelper.authenticating(this.serviceFutureStub, accessToken).getTransactionById(request));
}
@Override
public Single<TransactionV2> getTransactionById(
String transactionId, Set<String> requestingParties) {
return getTransactionById(transactionId, requestingParties, Optional.empty());
}
@Override
public Single<TransactionV2> getTransactionById(
String transactionId, Set<String> requestingParties, String accessToken) {
return getTransactionById(transactionId, requestingParties, Optional.of(accessToken));
}
}

View File

@ -4,29 +4,30 @@
package com.daml.ledger.rxjava
import java.time.Instant
import java.util.UUID
import java.util.concurrent.TimeUnit
import com.daml.ledger.javaapi.data.LedgerOffset.Absolute
import com.daml.ledger.api.v1.command_completion_service.Checkpoint
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.javaapi.data.ParticipantOffsetV2.Absolute
import com.daml.ledger.javaapi.data.{
Command,
CommandsSubmission,
CommandsSubmissionV2,
CreateCommand,
DamlRecord,
Identifier,
}
import com.daml.ledger.rxjava.grpc.helpers._
import com.digitalasset.canton.ledger.api.auth.{AuthService, AuthServiceWildcard}
import com.daml.ledger.api.v1.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v1.command_service.{
SubmitAndWaitForTransactionIdResponse,
import com.daml.ledger.api.v2.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v2.command_service.{
SubmitAndWaitForTransactionResponse,
SubmitAndWaitForTransactionTreeResponse,
SubmitAndWaitForUpdateIdResponse,
}
import com.daml.ledger.api.v1.event_query_service.{
GetEventsByContractIdResponse,
GetEventsByContractKeyResponse,
}
import com.daml.ledger.api.v1.ledger_configuration_service.GetLedgerConfigurationResponse
import com.daml.ledger.api.v2.event_query_service.GetEventsByContractIdResponse
import com.daml.ledger.api.v1.package_service._
import com.daml.ledger.api.v2.command_submission_service.SubmitResponse
import com.google.protobuf.ByteString
import com.google.protobuf.empty.Empty
import io.grpc.Server
@ -37,6 +38,7 @@ import org.scalatest.matchers.should.Matchers
import scala.concurrent.Future
import scala.jdk.CollectionConverters._
import scala.util.chaining.scalaUtilChainingOps
class DamlLedgerClientTest
extends AnyFlatSpec
@ -47,23 +49,13 @@ class DamlLedgerClientTest
val ledgerServices = new LedgerServices(getClass.getSimpleName)
behavior of "DamlLedgerClient.forLedgerIdAndHost"
behavior of "DamlLedgerClient.forHost"
it should "connect to an existing ledger-api grpc service with the correct ledgerId and pass the ledgerId to the clients" in {
it should "connect to an existing ledger-api grpc service and use it in the clients" in {
withFakeLedgerServer(AuthServiceWildcard) { (server, impls) =>
val damlLedgerClient = DamlLedgerClient
.newBuilder("localhost", server.getPort)
.withExpectedLedgerId(ledgerServices.ledgerId)
.build(): @annotation.nowarn(
"cat=deprecation&origin=com\\.daml\\.ledger\\.rxjava\\.DamlLedgerClient\\.Builder\\.withExpectedLedgerId"
)
testDamlLedgerClient(damlLedgerClient, impls)
}
}
it should "connect to an existing ledger-api grpc service, autodiscover the ledgerId and pass it to the clients" in {
withFakeLedgerServer(AuthServiceWildcard) { (server, impls) =>
val damlLedgerClient = DamlLedgerClient.newBuilder("localhost", server.getPort).build()
.build()
testDamlLedgerClient(damlLedgerClient, impls)
}
}
@ -72,16 +64,12 @@ class DamlLedgerClientTest
withFakeLedgerServer(mockedAuthService) { (server, ledgerServicesImpls) =>
val damlLedgerClient = DamlLedgerClient
.newBuilder("localhost", server.getPort)
.withExpectedLedgerId(ledgerServices.ledgerId)
.withAccessToken(somePartyReadWriteToken)
.build(): @annotation.nowarn(
"cat=deprecation&origin=com\\.daml\\.ledger\\.rxjava\\.DamlLedgerClient\\.Builder\\.withExpectedLedgerId"
)
.build()
damlLedgerClient.connect()
damlLedgerClient.getLedgerId shouldBe ledgerServices.ledgerId
testActiveContractSetClient(
damlLedgerClient.getActiveContractSetClient,
ledgerServicesImpls.activeContractsServiceImpl,
testStateServiceClient(
damlLedgerClient.getStateClient,
ledgerServicesImpls.stateServiceImpl,
)
testCommandClient(damlLedgerClient.getCommandClient, ledgerServicesImpls.commandServiceImpl)
testCommandCompletionClient(
@ -92,11 +80,7 @@ class DamlLedgerClientTest
damlLedgerClient.getCommandSubmissionClient,
ledgerServicesImpls.commandSubmissionServiceImpl,
)
testLedgerConfigurationClient(
damlLedgerClient.getLedgerConfigurationClient,
ledgerServicesImpls.ledgerConfigurationServiceImpl,
)
testTimeClientGet(damlLedgerClient.getTimeClient, ledgerServicesImpls.timeServiceImpl)
testTimeClientGet(damlLedgerClient.getTimeClient)
expectPermissionDenied {
testTimeClientSet(damlLedgerClient.getTimeClient, ledgerServicesImpls.timeServiceImpl)
}
@ -106,17 +90,16 @@ class DamlLedgerClientTest
}
private def clueFor(clientName: String): String =
s"DamlLedgerClient failed to propagate ledgerId to the $clientName:"
s"DamlLedgerClient failed to activate $clientName:"
private def testDamlLedgerClient(
damlLedgerClient: DamlLedgerClient,
ledgerServicesImpls: LedgerServicesImpls,
): Any = {
damlLedgerClient.connect()
damlLedgerClient.getLedgerId shouldBe ledgerServices.ledgerId
testActiveContractSetClient(
damlLedgerClient.getActiveContractSetClient,
ledgerServicesImpls.activeContractsServiceImpl,
testStateServiceClient(
damlLedgerClient.getStateClient,
ledgerServicesImpls.stateServiceImpl,
)
testCommandClient(damlLedgerClient.getCommandClient, ledgerServicesImpls.commandServiceImpl)
testCommandCompletionClient(
@ -127,28 +110,25 @@ class DamlLedgerClientTest
damlLedgerClient.getCommandSubmissionClient,
ledgerServicesImpls.commandSubmissionServiceImpl,
)
testLedgerConfigurationClient(
damlLedgerClient.getLedgerConfigurationClient,
ledgerServicesImpls.ledgerConfigurationServiceImpl,
)
testTimeClientGet(damlLedgerClient.getTimeClient, ledgerServicesImpls.timeServiceImpl)
testTimeClientGet(damlLedgerClient.getTimeClient)
testTimeClientSet(damlLedgerClient.getTimeClient, ledgerServicesImpls.timeServiceImpl)
testPackageClient(damlLedgerClient.getPackageClient, ledgerServicesImpls.packageServiceImpl)
damlLedgerClient.close()
}
private def testActiveContractSetClient(
activeContractSetClient: ActiveContractsClient,
activeContractsServiceImpl: ActiveContractsServiceImpl,
private def testStateServiceClient(
stateServiceClient: StateClient,
activeContractsServiceImpl: StateServiceImpl,
): Assertion = {
withClue(clueFor("ActiveContractsClient")) {
activeContractSetClient
withClue(clueFor("StateClient")) {
stateServiceClient
.getActiveContracts(filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.toList
activeContractsServiceImpl.getLastRequest.value.ledgerId shouldBe ledgerServices.ledgerId
activeContractsServiceImpl.getLastRequest.value.filter
.flatMap(_.filtersByParty.get(someParty)) should not be empty
}
}
@ -161,20 +141,33 @@ class DamlLedgerClientTest
val record = new DamlRecord(recordId, List.empty[DamlRecord.Field].asJava)
val command = new CreateCommand(new Identifier("a", "a", "b"), record)
val commands = genCommands(List(command), Option(someParty))
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
commandClient
.submitAndWait(params)
.timeout(1L, TimeUnit.SECONDS)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
commandServiceImpl.getLastRequest.value.getCommands.ledgerId shouldBe ledgerServices.ledgerId
commandServiceImpl.getLastRequest.value.getCommands.domainId shouldBe domainId
}
}
@ -184,15 +177,10 @@ class DamlLedgerClientTest
): Assertion = {
withClue(clueFor("CommandCompletionClient")) {
commandCompletionClient
.completionStream("applicationId", new Absolute(""), Set(someParty).asJava)
.completionStream("applicationId", new Absolute(""), List(someParty).asJava)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
commandCompletionServiceImpl.getLastCompletionStreamRequest.value.ledgerId shouldBe ledgerServices.ledgerId
commandCompletionClient
.completionEnd()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
commandCompletionServiceImpl.getLastCompletionEndRequest.value.ledgerId shouldBe ledgerServices.ledgerId
commandCompletionServiceImpl.getLastCompletionStreamRequest.value.applicationId shouldBe "applicationId"
}
}
@ -205,32 +193,44 @@ class DamlLedgerClientTest
val record = new DamlRecord(recordId, List.empty[DamlRecord.Field].asJava)
val command = new CreateCommand(new Identifier("a", "a", "b"), record)
val commands = genCommands(List[Command](command), Option(someParty))
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
commandSubmissionClient
.submit(params)
.timeout(1L, TimeUnit.SECONDS)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
commandSubmissionServiceImpl.getSubmittedRequest.value.getCommands.ledgerId shouldBe ledgerServices.ledgerId
commandSubmissionServiceImpl.getSubmittedRequest.value.getCommands.domainId shouldBe domainId
}
}
private def testTimeClientGet(
timeClient: TimeClient,
timeServiceImpl: TimeServiceImpl,
timeClient: TimeClient
): Assertion = {
withClue("TimeClientGet") {
timeClient.getTime
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
timeServiceImpl.getLastGetTimeRequest.value.ledgerId shouldBe ledgerServices.ledgerId
succeed
}
}
@ -239,23 +239,12 @@ class DamlLedgerClientTest
timeServiceImpl: TimeServiceImpl,
): Assertion = {
withClue("TimeClientSet") {
val newTime = Instant.ofEpochSecond(10L)
timeClient
.setTime(Instant.EPOCH, Instant.ofEpochSecond(10L))
.setTime(Instant.EPOCH, newTime)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
timeServiceImpl.getLastSetTimeRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
private def testLedgerConfigurationClient(
ledgerConfigurationClient: LedgerConfigurationClient,
ledgerConfigurationServiceImpl: LedgerConfigurationServiceImpl,
): Assertion = {
withClue("LedgerConfigurationClient") {
ledgerConfigurationClient.getLedgerConfiguration
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
ledgerConfigurationServiceImpl.getLastRequest.value.ledgerId shouldBe ledgerServices.ledgerId
timeServiceImpl.getLastSetTimeRequest.value.newTime.map(_.seconds) shouldBe Some(10L)
}
}
@ -268,17 +257,16 @@ class DamlLedgerClientTest
.listPackages()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
packageServiceImpl.getLastListPackageRequest.value.ledgerId shouldBe ledgerServices.ledgerId
packageClient
.getPackage("packageId")
.getPackage("packageIdA")
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
packageServiceImpl.getLastGetPackagesRequest.value.ledgerId shouldBe ledgerServices.ledgerId
packageServiceImpl.getLastGetPackagesRequest.value.packageId shouldBe "packageIdA"
packageClient
.getPackageStatus("packageId")
.getPackageStatus("packageIdB")
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
packageServiceImpl.getLastGetPackageStatusRequest.value.ledgerId shouldBe ledgerServices.ledgerId
packageServiceImpl.getLastGetPackageStatusRequest.value.packageId shouldBe "packageIdB"
}
}
@ -289,17 +277,19 @@ class DamlLedgerClientTest
ledgerServices.withFakeLedgerServer(
Observable.fromArray(genGetActiveContractsResponse),
Observable.empty(),
Future.successful(SubmitResponse.defaultInstance),
List(
CompletionStreamResponse(
Some(Checkpoint(offset = Some(LedgerOffset(LedgerOffset.Value.Absolute("1"))))),
None,
)
),
Future.successful(Empty.defaultInstance),
List(CompletionStreamResponse(None, Seq())),
genCompletionEndResponse("completionEndResponse"),
Future.successful(Empty.defaultInstance),
Future.successful(SubmitAndWaitForTransactionIdResponse.defaultInstance),
Future.successful(SubmitAndWaitForUpdateIdResponse.defaultInstance),
Future.successful(SubmitAndWaitForTransactionResponse.defaultInstance),
Future.successful(SubmitAndWaitForTransactionTreeResponse.defaultInstance),
List(genGetTimeResponse),
Seq(GetLedgerConfigurationResponse.defaultInstance),
Future.successful(genGetTimeResponse),
Future.successful(GetEventsByContractIdResponse.defaultInstance),
Future.successful(GetEventsByContractKeyResponse.defaultInstance),
Future.successful(ListPackagesResponse(Seq("id1"))),
Future.successful(GetPackageResponse(HashFunction.SHA256, ByteString.EMPTY)),
Future.successful(GetPackageStatusResponse(PackageStatus.values.head)),

View File

@ -1,113 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.util.concurrent.TimeUnit
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import io.reactivex.Observable
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import scala.concurrent.ExecutionContext
import scala.jdk.CollectionConverters._
class ActiveContractClientImplTest
extends AnyFlatSpec
with Matchers
with AuthMatchers
with OptionValues
with DataLayerHelpers {
val ledgerServices = new LedgerServices("active-contract-service-ledger")
implicit val ec: ExecutionContext = ledgerServices.executionContext
behavior of "[1.1] ActiveContractClientImpl.getActiveContracts"
it should "support the empty ACS" in {
ledgerServices.withACSClient(Observable.empty()) { (acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 0
}
}
it should "support ACS with one element" in {
ledgerServices.withACSClient(Observable.fromArray(genGetActiveContractsResponse)) {
(acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 1
}
}
it should "support ACS with 10 elements" in {
val acsResponses = List.fill(10)(genGetActiveContractsResponse)
ledgerServices.withACSClient(Observable.fromArray(acsResponses: _*)) { (acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 10
}
}
behavior of "[1.2] ActiveContractClientImpl.getActiveContracts"
it should "pass the transaction filter and the verbose flag to the ledger" in {
ledgerServices.withACSClient(Observable.empty()) { (acsClient, acsImpl) =>
val verbose = true
acsClient
.getActiveContracts(filterNothing, verbose)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
acsImpl.getLastRequest.value.getFilter.filtersByParty shouldBe filterNothing.getPartyToFilters.asScala
acsImpl.getLastRequest.value.verbose shouldBe verbose
}
}
behavior of "[1.3] ActiveContractClientImpl.getActiveContracts"
it should "send requests with the correct ledger ID" in {
ledgerServices.withACSClient(Observable.empty()) { (acsClient, acsImpl) =>
val verbose = true
acsClient
.getActiveContracts(filterNothing, verbose)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
acsImpl.getLastRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
"ActiveContractClientImpl.getActiveContracts" should "fail with insufficient authorization" in {
ledgerServices.withACSClient(Observable.empty(), mockedAuthService) { (acsClient, _) =>
expectUnauthenticated {
acsClient
.getActiveContracts(filterFor(someParty), false, emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
}
}
}
"ActiveContractClientImpl.getActiveContracts" should "succeed with sufficient authorization" in {
ledgerServices.withACSClient(Observable.empty(), mockedAuthService) { (acsClient, _) =>
acsClient
.getActiveContracts(filterFor(someParty), false, somePartyReadToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size shouldEqual 0
}
}
}

View File

@ -4,14 +4,14 @@
package com.daml.ledger.rxjava.grpc
import com.digitalasset.canton.ledger.api.auth.{AuthService, AuthServiceWildcard}
import com.daml.ledger.api.v1.command_service.{
SubmitAndWaitForTransactionIdResponse,
import com.daml.ledger.api.v2.command_service.{
SubmitAndWaitForTransactionResponse,
SubmitAndWaitForTransactionTreeResponse,
SubmitAndWaitForUpdateIdResponse,
}
import com.daml.ledger.javaapi.data.{
Command,
CommandsSubmission,
CommandsSubmissionV2,
CreateCommand,
DamlRecord,
Identifier,
@ -23,12 +23,13 @@ import io.reactivex.Single
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import java.util.UUID.randomUUID
import java.util.concurrent.TimeUnit
import java.util.Optional
import java.util.{Optional, UUID}
import scala.concurrent.Future
import scala.jdk.CollectionConverters._
import scala.util.chaining.scalaUtilChainingOps
class CommandClientImplTest
extends AnyFlatSpec
@ -42,7 +43,7 @@ class CommandClientImplTest
private def withCommandClient(authService: AuthService = AuthServiceWildcard) = {
ledgerServices.withCommandClient(
Future.successful(Empty.defaultInstance),
Future.successful(SubmitAndWaitForTransactionIdResponse.defaultInstance),
Future.successful(SubmitAndWaitForUpdateIdResponse.defaultInstance),
Future.successful(SubmitAndWaitForTransactionResponse.defaultInstance),
Future.successful(SubmitAndWaitForTransactionTreeResponse.defaultInstance),
authService,
@ -58,12 +59,25 @@ class CommandClientImplTest
it should "send the given command to the Ledger" in {
withCommandClient() { (client, service) =>
val commands = genCommands(List.empty)
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val domainId = UUID.randomUUID().toString
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
client
.submitAndWait(params)
@ -82,14 +96,27 @@ class CommandClientImplTest
val record = new DamlRecord(recordId, List.empty[DamlRecord.Field].asJava)
val command = new CreateCommand(new Identifier("a", "a", "b"), record)
val commands = genCommands(List(command))
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withWorkflowId(commands.getWorkflowId)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
client
.submitAndWait(params)
@ -103,7 +130,7 @@ class CommandClientImplTest
service.getLastRequest.value.getCommands.readAs shouldBe commands.getReadAs.asScala
commands.getActAs.get(0) shouldBe commands.getParty
service.getLastRequest.value.getCommands.workflowId shouldBe commands.getWorkflowId
service.getLastRequest.value.getCommands.ledgerId shouldBe ledgerServices.ledgerId
service.getLastRequest.value.getCommands.domainId shouldBe domainId
service.getLastRequest.value.getCommands.minLedgerTimeRel
.map(_.seconds) shouldBe commands.getMinLedgerTimeRelative.asScala.map(_.getSeconds)
service.getLastRequest.value.getCommands.minLedgerTimeRel
@ -133,19 +160,20 @@ class CommandClientImplTest
List(command).asJava
}
private type SubmitAndWait[A] = CommandsSubmission => Single[A]
private type SubmitAndWait[A] = CommandsSubmissionV2 => Single[A]
private def submitAndWaitFor[A](
submit: SubmitAndWait[A]
)(commands: java.util.List[Command], party: String, token: Option[String]) = {
val params = CommandsSubmission
val params = CommandsSubmissionV2
.create(
randomUUID().toString,
randomUUID().toString,
randomUUID().toString,
token.fold(dummyCommands)(_ => commands),
)
.withActAs(party)
.withAccessToken(Optional.ofNullable(token.orNull))
.pipe(p => token.fold(p)(p.withAccessToken))
submit(params).timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS).blockingGet()
}

View File

@ -3,15 +3,16 @@
package com.daml.ledger.rxjava.grpc
import java.util.Optional
import java.util.concurrent.TimeUnit
import com.daml.ledger.javaapi.data.LedgerOffset
import com.daml.ledger.javaapi.data.LedgerOffset.LedgerBegin
import com.daml.ledger.api.v1.command_completion_service.Checkpoint
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.javaapi.data.ParticipantOffsetV2.ParticipantBegin
import com.daml.ledger.javaapi.data.LedgerOffset.Absolute
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import com.daml.ledger.api.v1.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v1.completion.Completion
import com.daml.ledger.api.v2.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v2.completion.Completion
import com.google.rpc.status.Status
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
@ -27,34 +28,8 @@ class CommandCompletionClientImplTest
with DataLayerHelpers {
val ledgerServices = new LedgerServices("command-completion-service-ledger")
behavior of "[4.1] CommandCompletionClientImpl.getLedgerEnd"
it should "return the ledger end" in {
val offset = "offset"
val response = genCompletionEndResponse(offset)
ledgerServices.withCommandCompletionClient(List.empty, response) { (client, _) =>
val end = client
.completionEnd()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
end.getOffset shouldBe a[LedgerOffset.Absolute]
end.getOffset.asInstanceOf[LedgerOffset.Absolute].getOffset shouldBe offset
}
}
behavior of "[4.2] CommandCompletionClientImpl.completionEnd"
it should "send the request with the correct ledgerId" in {
ledgerServices.withCommandCompletionClient(List.empty, genCompletionEndResponse("")) {
(client, serviceImpl) =>
client
.completionEnd()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
serviceImpl.getLastCompletionEndRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
private val offset1 = LedgerOffset(LedgerOffset.Value.Absolute("1"))
private val offset2 = LedgerOffset(LedgerOffset.Value.Absolute("2"))
behavior of "[4.3] CommandCompletionClientImpl.completionStream"
@ -62,50 +37,52 @@ class CommandCompletionClientImplTest
val applicationId = "applicationId"
val completion1 = Completion("cid1", Option(new Status(0)), "1")
val completion2 = Completion("cid2", Option(new Status(1)))
val completionResponse = CompletionStreamResponse(None, List(completion1, completion2))
val completionResponses = List(
CompletionStreamResponse(Some(Checkpoint(offset = Some(offset1))), Some(completion1)),
CompletionStreamResponse(Some(Checkpoint(offset = Some(offset2))), Some(completion2)),
)
ledgerServices.withCommandCompletionClient(
List(completionResponse),
genCompletionEndResponse(""),
completionResponses
) { (client, _) =>
val completions = client
.completionStream(applicationId, LedgerBegin.getInstance(), Set("Alice").asJava)
.take(1)
.completionStream(applicationId, ParticipantBegin.getInstance(), List("Alice").asJava)
.take(2)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.iterator()
.next()
completions.getCheckpoint shouldBe Optional.empty()
completions.getCompletions.size() shouldBe 2
val receivedCompletion1 = completions.getCompletions.get(0)
val receivedCompletion2 = completions.getCompletions.get(1)
receivedCompletion1.getCommandId shouldBe completion1.commandId
receivedCompletion1.getStatus.getCode shouldBe completion1.getStatus.code
receivedCompletion1.getTransactionId shouldBe completion1.transactionId
receivedCompletion2.getCommandId shouldBe completion2.commandId
receivedCompletion2.getStatus.getCode shouldBe completion2.getStatus.code
val receivedCompletion1 = completions.next()
val receivedCompletion2 = completions.next()
receivedCompletion1.getCheckpoint.getOffset shouldBe new Absolute(offset1.getAbsolute)
receivedCompletion1.getCompletion.getCommandId shouldBe completion1.commandId
receivedCompletion1.getCompletion.getStatus.getCode shouldBe completion1.getStatus.code
receivedCompletion1.getCompletion.getUpdateId shouldBe completion1.updateId
receivedCompletion2.getCheckpoint.getOffset shouldBe new Absolute(offset2.getAbsolute)
receivedCompletion2.getCompletion.getCommandId shouldBe completion2.commandId
receivedCompletion2.getCompletion.getStatus.getCode shouldBe completion2.getStatus.code
}
}
behavior of "[4.4] CommandCompletionClientImpl.completionStream"
it should "send the request with the correct ledgerId" in {
it should "send the request with the correct arguments" in {
val applicationId = "applicationId"
val completion1 = Completion("cid1", Option(new Status(0)))
val completionResponse = CompletionStreamResponse(None, List(completion1))
val parties = Set("Alice")
val completionResponse =
CompletionStreamResponse(Some(Checkpoint(offset = Some(offset1))), Some(completion1))
val parties = List("Alice")
ledgerServices.withCommandCompletionClient(
List(completionResponse),
genCompletionEndResponse(""),
List(completionResponse)
) { (client, serviceImpl) =>
client
.completionStream(applicationId, LedgerBegin.getInstance(), parties.asJava)
.completionStream(applicationId, ParticipantBegin.getInstance(), parties.asJava)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
serviceImpl.getLastCompletionStreamRequest.value.ledgerId shouldBe ledgerServices.ledgerId
serviceImpl.getLastCompletionStreamRequest.value.applicationId shouldBe applicationId
serviceImpl.getLastCompletionStreamRequest.value.getOffset.getAbsolute shouldBe "" // grpc default string is empty string
serviceImpl.getLastCompletionStreamRequest.value.getOffset.getBoundary.isLedgerEnd shouldBe false
serviceImpl.getLastCompletionStreamRequest.value.getOffset.getBoundary.isLedgerBegin shouldBe true
serviceImpl.getLastCompletionStreamRequest.value.getBeginExclusive.getAbsolute shouldBe "" // grpc default string is empty string
serviceImpl.getLastCompletionStreamRequest.value.getBeginExclusive.getBoundary.isParticipantEnd shouldBe false
serviceImpl.getLastCompletionStreamRequest.value.getBeginExclusive.getBoundary.isParticipantBegin shouldBe true
serviceImpl.getLastCompletionStreamRequest.value.parties should contain theSameElementsAs parties
}
}
@ -114,10 +91,10 @@ class CommandCompletionClientImplTest
def toAuthenticatedServer(fn: CommandCompletionClient => Any): Any = {
val completion1 = Completion("cid1", Option(new Status(0)))
val completionResponse = CompletionStreamResponse(None, List(completion1))
val completionResponse =
CompletionStreamResponse(Some(Checkpoint(offset = Some(offset1))), Some(completion1))
ledgerServices.withCommandCompletionClient(
List(completionResponse),
genCompletionEndResponse(""),
mockedAuthService,
) { (client, _) =>
fn(client)
@ -129,7 +106,7 @@ class CommandCompletionClientImplTest
withClue("completionStream") {
expectUnauthenticated {
client
.completionStream("appId", LedgerBegin.getInstance(), Set(someParty).asJava)
.completionStream("appId", ParticipantBegin.getInstance(), List(someParty).asJava)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
}
@ -137,16 +114,11 @@ class CommandCompletionClientImplTest
withClue("completionStream unbounded") {
expectUnauthenticated {
client
.completionStream("appId", Set(someParty).asJava)
.completionStream("appId", List(someParty).asJava)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
}
}
withClue("completionEnd") {
expectUnauthenticated {
client.completionEnd().blockingGet()
}
}
}
}
@ -157,8 +129,8 @@ class CommandCompletionClientImplTest
client
.completionStream(
"appId",
LedgerBegin.getInstance(),
Set(someParty).asJava,
ParticipantBegin.getInstance(),
List(someParty).asJava,
someOtherPartyReadToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
@ -168,16 +140,11 @@ class CommandCompletionClientImplTest
withClue("completionStream unbounded") {
expectPermissionDenied {
client
.completionStream("appId", Set(someParty).asJava, someOtherPartyReadToken)
.completionStream("appId", List(someParty).asJava, someOtherPartyReadToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
}
}
withClue("completionEnd") {
expectUnauthenticated {
client.completionEnd(emptyToken).blockingGet()
}
}
}
}
@ -187,8 +154,8 @@ class CommandCompletionClientImplTest
client
.completionStream(
"appId",
LedgerBegin.getInstance(),
Set(someParty).asJava,
ParticipantBegin.getInstance(),
List(someParty).asJava,
somePartyReadToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
@ -196,13 +163,10 @@ class CommandCompletionClientImplTest
}
withClue("completionStream unbounded") {
client
.completionStream("appId", Set(someParty).asJava, somePartyReadToken)
.completionStream("appId", List(someParty).asJava, somePartyReadToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
}
withClue("completionEnd") {
client.completionEnd(somePartyReadToken).blockingGet()
}
}
}

View File

@ -5,24 +5,26 @@ package com.daml.ledger.rxjava.grpc
import com.daml.ledger.javaapi.data.{
Command,
CommandsSubmission,
CommandsSubmissionV2,
CreateCommand,
DamlRecord,
Identifier,
}
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import com.google.protobuf.empty.Empty
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import java.time.Duration
import java.time.temporal.ChronoUnit
import java.util.Optional
import java.util.{Optional, UUID}
import java.util.concurrent.TimeUnit
import com.daml.ledger.api.v2.command_submission_service.SubmitResponse
import scala.concurrent.Future
import scala.jdk.CollectionConverters._
import scala.util.chaining.scalaUtilChainingOps
class CommandSubmissionClientImplTest
extends AnyFlatSpec
@ -47,13 +49,26 @@ class CommandSubmissionClientImplTest
timeout = Optional.of(Duration.of(5, ChronoUnit.SECONDS)),
) { (client, _) =>
val commands = genCommands(List.empty)
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
withClue("The first command should be stuck") {
expectDeadlineExceeded(
@ -79,14 +94,27 @@ class CommandSubmissionClientImplTest
it should "send a commands to the ledger" in {
ledgerServices.withCommandSubmissionClient(alwaysSucceed) { (client, serviceImpl) =>
val commands = genCommands(List.empty)
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withWorkflowId(commands.getWorkflowId)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
client
.submit(params)
@ -95,7 +123,7 @@ class CommandSubmissionClientImplTest
val receivedCommands = serviceImpl.getSubmittedRequest.value.getCommands
receivedCommands.ledgerId shouldBe ledgerServices.ledgerId
receivedCommands.domainId shouldBe domainId
receivedCommands.applicationId shouldBe commands.getApplicationId
receivedCommands.workflowId shouldBe commands.getWorkflowId
receivedCommands.commandId shouldBe commands.getCommandId
@ -136,14 +164,27 @@ class CommandSubmissionClientImplTest
val record = new DamlRecord(recordId, List.empty[DamlRecord.Field].asJava)
val command = new CreateCommand(new Identifier("a", "a", "b"), record)
val commands = genCommands(List[Command](command), Option(someParty))
val domainId = UUID.randomUUID().toString
val params = CommandsSubmission
.create(commands.getApplicationId, commands.getCommandId, commands.getCommands)
val params = CommandsSubmissionV2
.create(commands.getApplicationId, commands.getCommandId, domainId, commands.getCommands)
.withActAs(commands.getParty)
.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute)
.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative)
.withDeduplicationTime(commands.getDeduplicationTime)
.withAccessToken(Optional.ofNullable(accessToken.orNull))
.pipe(p =>
if (commands.getMinLedgerTimeAbsolute.isPresent)
p.withMinLedgerTimeAbs(commands.getMinLedgerTimeAbsolute.get())
else p
)
.pipe(p =>
if (commands.getMinLedgerTimeRelative.isPresent)
p.withMinLedgerTimeRel(commands.getMinLedgerTimeRelative.get())
else p
)
.pipe(p =>
if (commands.getDeduplicationTime.isPresent)
p.withDeduplicationDuration(commands.getDeduplicationTime.get())
else p
)
.pipe(p => accessToken.fold(p)(p.withAccessToken))
client
.submit(params)
@ -189,11 +230,14 @@ object CommandSubmissionClientImplTest {
private val stuck = Future.never
private val success = Future.successful(Empty.defaultInstance)
private val success = Future.successful(SubmitResponse.defaultInstance)
private val alwaysSucceed: () => Future[Empty] = () => success
private val alwaysSucceed: () => Future[SubmitResponse] = () => success
private def sequence(first: Future[Empty], following: Future[Empty]*): () => Future[Empty] = {
private def sequence(
first: Future[SubmitResponse],
following: Future[SubmitResponse]*
): () => Future[SubmitResponse] = {
val it = Iterator.single(first) ++ Iterator(following: _*)
() =>
try {

View File

@ -5,11 +5,7 @@ package com.daml.ledger.rxjava.grpc
import com.digitalasset.canton.ledger.api.auth.{AuthService, AuthServiceWildcard}
import com.daml.ledger.rxjava.grpc.helpers.TestConfiguration
import com.daml.ledger.api.v1.event_query_service.{
GetEventsByContractIdResponse,
GetEventsByContractKeyResponse,
}
import com.daml.ledger.javaapi.data._
import com.daml.ledger.api.v2.event_query_service.GetEventsByContractIdResponse
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices}
import org.scalatest.OptionValues
@ -18,7 +14,6 @@ import org.scalatest.matchers.should.Matchers
import java.util.concurrent.TimeUnit
import scala.concurrent.Future
import scala.jdk.CollectionConverters._
import scala.jdk.OptionConverters._
class EventQueryClientImplTest
extends AnyFlatSpec
@ -32,13 +27,10 @@ class EventQueryClientImplTest
private def withEventQueryClient(authService: AuthService = AuthServiceWildcard) = {
ledgerServices.withEventQueryClient(
Future.successful(GetEventsByContractIdResponse.defaultInstance),
Future.successful(GetEventsByContractKeyResponse.defaultInstance),
authService,
) _
}
private val contractKey = Bool.TRUE
private val identifier = new Identifier("recordPackageId", "recordModuleName", "recordEntityName")
private val contractId = "contract_id"
private val parties = java.util.Set.of("party_1")
@ -51,28 +43,6 @@ class EventQueryClientImplTest
.blockingGet()
service.getLastGetEventsByContractIdRequest.value.contractId shouldBe contractId
service.getLastGetEventsByContractIdRequest.value.requestingParties.toSet shouldBe parties.asScala
client
.getEventsByContractKey(contractKey, identifier, parties, "1")
.blockingGet()
service.getLastGetEventsByContractKeyRequest.value.contractKey
.flatMap(_.sum.bool) shouldBe contractKey.asBool().toScala.map(_.getValue)
service.getLastGetEventsByContractKeyRequest.value.templateId.map(_.packageId) shouldBe Some(
identifier.getPackageId
)
service.getLastGetEventsByContractKeyRequest.value.templateId.map(_.entityName) shouldBe Some(
identifier.getEntityName
)
service.getLastGetEventsByContractKeyRequest.value.templateId.map(_.moduleName) shouldBe Some(
identifier.getModuleName
)
service.getLastGetEventsByContractKeyRequest.value.requestingParties.toSet shouldBe parties.asScala
service.getLastGetEventsByContractKeyRequest.value.continuationToken shouldBe "1"
client
.getEventsByContractKey(contractKey, identifier, parties, "")
.blockingGet()
service.getLastGetEventsByContractKeyRequest.value.continuationToken shouldBe ""
}
}
@ -88,14 +58,6 @@ class EventQueryClientImplTest
.blockingGet()
}
}
withClue("getEventsByContractKey") {
expectUnauthenticated {
client
.getEventsByContractKey(contractKey, identifier, parties, "")
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
}
}
}
}
@ -109,20 +71,6 @@ class EventQueryClientImplTest
.blockingGet()
}
}
withClue("getEventsByContractKey") {
expectPermissionDenied {
client
.getEventsByContractKey(
contractKey,
identifier,
parties,
"",
someOtherPartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
}
}
}
}
@ -134,12 +82,6 @@ class EventQueryClientImplTest
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
}
withClue("getEventsByContractKey") {
client
.getEventsByContractKey(contractKey, identifier, parties, "", somePartyReadWriteToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
}
}
}

View File

@ -1,86 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.util.concurrent.TimeUnit
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{LedgerServices, TestConfiguration}
import com.daml.ledger.api.v1.ledger_configuration_service.GetLedgerConfigurationResponse
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
final class LedgerConfigurationClientImplTest
extends AnyFlatSpec
with Matchers
with AuthMatchers
with OptionValues {
private val ledgerServices = new LedgerServices("ledger-configuration-service-ledger")
behavior of "[5.1] LedgerConfigurationClientImpl.getLedgerConfiguration"
it should "send the request to the Ledger" in {
ledgerServices.withConfigurationClient(Seq(GetLedgerConfigurationResponse.defaultInstance)) {
(client, _) =>
// to test that we send a request to the Ledger, we check if there is a response
client.getLedgerConfiguration
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
}
}
behavior of "[5.2] LedgerConfigurationClientImpl.getLedgerConfiguration"
it should "send the request with the correct ledger ID" in {
ledgerServices.withConfigurationClient(Seq(GetLedgerConfigurationResponse.defaultInstance)) {
(client, service) =>
client.getLedgerConfiguration
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
service.getLastRequest.value.ledgerId shouldEqual ledgerServices.ledgerId
}
}
behavior of "Authorization"
def toAuthenticatedServer(fn: LedgerConfigurationClient => Any): Any =
ledgerServices.withConfigurationClient(
Seq(GetLedgerConfigurationResponse.defaultInstance),
mockedAuthService,
) { (client, _) =>
fn(client)
}
it should "deny access without a token" in {
expectUnauthenticated {
toAuthenticatedServer(
_.getLedgerConfiguration
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
)
}
}
it should "deny access with insufficient authorization" in {
expectUnauthenticated {
toAuthenticatedServer(
_.getLedgerConfiguration(emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
)
}
}
it should "allow access with sufficient authorization" in {
toAuthenticatedServer(
_.getLedgerConfiguration(publicToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
)
}
}

View File

@ -1,102 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.time.Duration
import java.time.temporal.ChronoUnit
import java.util.Optional
import java.util.concurrent.TimeUnit
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.{LedgerServices, TestConfiguration}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import scala.concurrent.Future
@deprecated("Ledger identity string is optional for all ledger API requests", since = "2.0.0")
final class LedgerIdentityClientTest extends AnyFlatSpec with Matchers with AuthMatchers {
import LedgerIdentityClientTest._
private val ledgerServices = new LedgerServices(ledgerId)
behavior of "[6.1] LedgerIdentityClient.getLedgerIdentity"
it should "return ledger-id when requested" in ledgerServices.withLedgerIdentityClient(
alwaysSucceed
) { (binding, _) =>
binding.getLedgerIdentity
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet() shouldBe ledgerServices.ledgerId
}
it should "return ledger-id when requested with authorization" in ledgerServices
.withLedgerIdentityClient(alwaysSucceed, mockedAuthService) { (binding, _) =>
binding
.getLedgerIdentity(publicToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet() shouldBe ledgerServices.ledgerId
}
it should "deny ledger-id queries with insufficient authorization" in ledgerServices
.withLedgerIdentityClient(alwaysSucceed, mockedAuthService) { (binding, _) =>
expectUnauthenticated {
binding
.getLedgerIdentity(emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
}
}
it should "timeout should work as expected across calls" in {
ledgerServices.withLedgerIdentityClient(
stepThrough(stuck, success),
timeout = Optional.of(Duration.of(5, ChronoUnit.SECONDS)),
) { (client, _) =>
withClue("The first command should be stuck") {
expectDeadlineExceeded(
client
.getLedgerIdentity(emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
)
}
withClue("The second command should go through") {
val res = Option(
client
.getLedgerIdentity(emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
)
res should not be empty
}
}
}
}
object LedgerIdentityClientTest {
private val ledgerId = "ledger-identity-service-ledger"
private val stuck = Future.never
private val success = Future.successful(ledgerId)
private val alwaysSucceed: () => Future[String] = () => success
private def stepThrough[A](first: A, following: A*): () => A = {
val it = Iterator.single(first) ++ Iterator(following: _*)
() =>
try {
it.next()
} catch {
case e: NoSuchElementException =>
throw new RuntimeException("LedgerIdentityClientImplTest.sequence exhausted", e)
}
}
}

View File

@ -34,22 +34,6 @@ class PackageClientImplTest extends AnyFlatSpec with Matchers with AuthMatchers
}
}
behavior of "[7.2] PackageClientImpl.listPackages"
it should "request the list of packages with the correct ledger ID" in {
ledgerServices.withPackageClient(
listPackageResponseFuture("first"),
defaultGetPackageResponseFuture,
defaultGetPackageStatusResponseFuture,
) { (client, service) =>
client
.listPackages()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
service.getLastListPackageRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "[7.3] PackageClientImpl.getPackage"
it should "return the package from the Ledger" in {
@ -69,7 +53,7 @@ class PackageClientImplTest extends AnyFlatSpec with Matchers with AuthMatchers
behavior of "[7.4] PackageClientImpl.getPackage"
it should "request the package with the correct ledger ID and package ID" in {
it should "request the package with the correct package ID" in {
ledgerServices.withPackageClient(
listPackageResponseFuture(),
defaultGetPackageResponseFuture,
@ -79,7 +63,6 @@ class PackageClientImplTest extends AnyFlatSpec with Matchers with AuthMatchers
.getPackage("packageId")
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
service.getLastGetPackagesRequest.value.ledgerId shouldEqual ledgerServices.ledgerId
service.getLastGetPackagesRequest.value.packageId shouldEqual "packageId"
}
}
@ -102,7 +85,7 @@ class PackageClientImplTest extends AnyFlatSpec with Matchers with AuthMatchers
behavior of "[7.6] PackageClientImpl.getPackageStatus"
it should "send a request with the correct ledger ID and packageID" in {
it should "send a request with the correct packageID" in {
ledgerServices.withPackageClient(
listPackageResponseFuture(),
defaultGetPackageResponseFuture,
@ -112,7 +95,6 @@ class PackageClientImplTest extends AnyFlatSpec with Matchers with AuthMatchers
.getPackageStatus("packageId")
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingGet()
service.getLastGetPackageStatusRequest.value.ledgerId shouldBe ledgerServices.ledgerId
service.getLastGetPackageStatusRequest.value.packageId shouldBe "packageId"
}
}

View File

@ -0,0 +1,128 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.util.concurrent.TimeUnit
import com.daml.ledger.javaapi.data.ParticipantOffsetV2
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.TransactionGenerator.nonEmptyLedgerContent
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import io.reactivex.Observable
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import scala.concurrent.ExecutionContext
import scala.jdk.CollectionConverters._
class StateClientImplTest
extends AnyFlatSpec
with ScalaCheckDrivenPropertyChecks
with Matchers
with AuthMatchers
with OptionValues
with DataLayerHelpers {
val ledgerServices = new LedgerServices("state-service-ledger")
implicit val ec: ExecutionContext = ledgerServices.executionContext
behavior of "[1.1] StateClientImpl.getActiveContracts"
it should "support the empty ACS" in {
ledgerServices.withACSClient(Observable.empty(), Observable.empty()) { (acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 0
}
}
it should "support ACS with one element" in {
ledgerServices.withACSClient(
Observable.fromArray(genGetActiveContractsResponse),
Observable.empty(),
) { (acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 1
}
}
it should "support ACS with 10 elements" in {
val acsResponses = List.fill(10)(genGetActiveContractsResponse)
ledgerServices.withACSClient(Observable.fromArray(acsResponses: _*), Observable.empty()) {
(acsClient, _) =>
val acs = acsClient
.getActiveContracts(filterNothing, true)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
acs.blockingIterable().asScala.size shouldBe 10
}
}
behavior of "[1.2] StateClientImpl.getActiveContracts"
it should "pass the transaction filter and the verbose flag to the ledger" in {
ledgerServices.withACSClient(Observable.empty(), Observable.empty()) { (acsClient, acsImpl) =>
val verbose = true
acsClient
.getActiveContracts(filterNothing, verbose)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
acsImpl.getLastRequest.value.getFilter.filtersByParty shouldBe filterNothing.getPartyToFilters.asScala
acsImpl.getLastRequest.value.verbose shouldBe verbose
}
}
behavior of "[1.3] StateClientImpl.getActiveContracts"
"StateClientImpl.getActiveContracts" should "fail with insufficient authorization" in {
ledgerServices.withACSClient(Observable.empty(), Observable.empty(), mockedAuthService) {
(acsClient, _) =>
expectUnauthenticated {
acsClient
.getActiveContracts(filterFor(someParty), false, emptyToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
}
}
}
"StateClientImpl.getActiveContracts" should "succeed with sufficient authorization" in {
ledgerServices.withACSClient(Observable.empty(), Observable.empty(), mockedAuthService) {
(acsClient, _) =>
acsClient
.getActiveContracts(filterFor(someParty), false, somePartyReadToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size shouldEqual 0
}
}
behavior of "[1.3] StateClientImpl.getLedgerEnd"
it should "provide ledger end from the ledger" in forAll(nonEmptyLedgerContent) {
case (ledgerContent, transactions) =>
ledgerServices.withACSClient(
Observable.empty(),
Observable.fromIterable(ledgerContent.asJava),
) { (stateClient, _) =>
val expectedOffset = new ParticipantOffsetV2.Absolute(transactions.last.getOffset)
stateClient.getLedgerEnd.blockingGet() shouldBe expectedOffset
}
}
it should "provide LEDGER_BEGIN from empty ledger" in
ledgerServices.withACSClient(Observable.empty(), Observable.empty()) { (transactionClient, _) =>
transactionClient.getLedgerEnd.blockingGet() shouldBe
ParticipantOffsetV2.ParticipantBegin.getInstance()
}
}

View File

@ -12,7 +12,7 @@ import org.scalatest.OptionValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import scala.concurrent.ExecutionContext
import scala.concurrent.{ExecutionContext, Future}
final class TimeClientImplTest
extends AnyFlatSpec
@ -26,9 +26,12 @@ final class TimeClientImplTest
behavior of "[9.1] TimeClientImpl.setTime"
it should "send requests with the correct ledger ID, current time and new time" in {
it should "send requests with the correct current time and new time" in {
val (timeService, timeServiceImpl) =
TimeServiceImpl.createWithRef(Seq.empty, ledgerServices.authorizer)
TimeServiceImpl.createWithRef(
Future.failed(new UnsupportedOperationException),
ledgerServices.authorizer,
)
ledgerServices.withTimeClient(Seq(timeService)) { timeClient =>
val currentLedgerTimeSeconds = 1L
val currentLedgerTimeNanos = 2L
@ -45,7 +48,6 @@ final class TimeClientImplTest
timeServiceImpl.getLastSetTimeRequest.value.getCurrentTime.nanos shouldBe currentLedgerTimeNanos
timeServiceImpl.getLastSetTimeRequest.value.getNewTime.seconds shouldBe newLedgerTimeSeconds
timeServiceImpl.getLastSetTimeRequest.value.getNewTime.nanos shouldBe newLedgerTimeNanos
timeServiceImpl.getLastSetTimeRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
@ -54,7 +56,11 @@ final class TimeClientImplTest
it should "return the responses received" in {
val getTimeResponse = genGetTimeResponse
ledgerServices.withTimeClient(
Seq(TimeServiceImpl.createWithRef(Seq(getTimeResponse), ledgerServices.authorizer)._1)
Seq(
TimeServiceImpl
.createWithRef(Future.successful(getTimeResponse), ledgerServices.authorizer)
._1
)
) { timeClient =>
val response = timeClient.getTime
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
@ -64,27 +70,18 @@ final class TimeClientImplTest
}
}
behavior of "[9.3] TimeClientImpl.getTime"
it should "send requests with the correct ledger ID" in {
val getTimeResponse =
genGetTimeResponse // we use the first element to block on the first element
val (service, impl) =
TimeServiceImpl.createWithRef(Seq(getTimeResponse), ledgerServices.authorizer)
ledgerServices.withTimeClient(Seq(service)) { timeClient =>
val _ = timeClient
.getTime()
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingFirst()
impl.getLastGetTimeRequest.value.ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "[9.4] TimeClientImpl.setTime"
it should "return an error without sending a request when the time to set if bigger than the current time" in {
ledgerServices.withTimeClient(
Seq(TimeServiceImpl.createWithRef(Seq.empty, ledgerServices.authorizer)._1)
Seq(
TimeServiceImpl
.createWithRef(
Future.failed(new UnsupportedOperationException),
ledgerServices.authorizer,
)
._1
)
) { timeClient =>
val currentTime = Instant.ofEpochSecond(1L, 2L)
intercept[RuntimeException](
@ -100,7 +97,11 @@ final class TimeClientImplTest
def toAuthenticatedServer(fn: TimeClient => Any): Any =
ledgerServices.withTimeClient(
Seq(TimeServiceImpl.createWithRef(Seq(genGetTimeResponse), ledgerServices.authorizer)._1),
Seq(
TimeServiceImpl
.createWithRef(Future.successful(genGetTimeResponse), ledgerServices.authorizer)
._1
),
mockedAuthService,
)(fn)

View File

@ -1,524 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.util.concurrent.TimeUnit
import com.daml.ledger.javaapi.data
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.TransactionGenerator._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset.Value.Absolute
import com.daml.ledger.api.v1.transaction_filter.TemplateFilter
import com.daml.ledger.api.v1.value.Identifier
import io.reactivex.Observable
import org.scalacheck.Shrink
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec
import scala.jdk.CollectionConverters._
final class TransactionsClientImplTest
extends AnyFlatSpec
with ScalaCheckDrivenPropertyChecks
with Matchers
with AuthMatchers
with DataLayerHelpers {
override val ledgerServices = new LedgerServices("transaction-service-ledger")
implicit def tupleNoShrink[A, B]: Shrink[(A, B)] = Shrink.shrinkAny
private val ledgerBegin = data.LedgerOffset.LedgerBegin.getInstance()
private val ledgerEnd = data.LedgerOffset.LedgerEnd.getInstance()
private val emptyFilter = new data.FiltersByParty(Map.empty[String, data.Filter].asJava)
behavior of "8.1 TransactionClient.getTransactions"
it should "return transactions from the ledger" in forAll(ledgerContentGen) {
case (ledgerContent, expectedTransactions) =>
ledgerServices.withTransactionsClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, _) =>
transactionClient
.getTransactions(ledgerBegin, ledgerEnd, emptyFilter, false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.toList shouldBe expectedTransactions
}
}
behavior of "8.2 TransactionClient.getTransactions"
it should "pass start offset, end offset, transaction filter and verbose flag with the request" in {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
val begin = new data.LedgerOffset.Absolute("1")
val end = new data.LedgerOffset.Absolute("2")
val transactionFilter = new data.FiltersByParty(
Map[String, data.Filter](
"Alice" -> data.InclusiveFilter.ofTemplateIds(
Set(
new data.Identifier("p1", "m1", "e1"),
new data.Identifier("p2", "m2", "e2"),
).asJava
)
).asJava
)
transactionClient
.getTransactions(begin, end, transactionFilter, true)
.toList()
.blockingGet()
val request = transactionService.lastTransactionsRequest.get()
request.begin shouldBe Some(LedgerOffset(Absolute("1")))
request.end shouldBe Some(LedgerOffset(Absolute("2")))
val filter = request.filter.get.filtersByParty
filter.keySet shouldBe Set("Alice")
filter("Alice").inclusive.get.templateFilters.toSet shouldBe Set(
TemplateFilter(
Some(Identifier("p1", moduleName = "m1", entityName = "e1")),
includeCreatedEventBlob = false,
),
TemplateFilter(
Some(Identifier("p2", moduleName = "m2", entityName = "e2")),
includeCreatedEventBlob = false,
),
)
request.verbose shouldBe true
}
}
behavior of "8.3 TransactionClient.getTransactions"
it should "request stream with the correct ledger id" in {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
transactionClient
.getTransactions(ledgerBegin, ledgerEnd, emptyFilter, false)
.toList()
.blockingGet()
transactionService.lastTransactionsRequest.get().ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "8.5 TransactionClient.getTransactionsTrees"
it should "return transaction trees from the ledger" ignore forAll(ledgerContentTreeGen) {
case (ledgerContent, expectedTransactionsTrees) =>
ledgerServices.withTransactionsClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, _) =>
transactionClient
.getTransactionsTrees(ledgerBegin, ledgerEnd, emptyFilter, false)
.blockingIterable()
.asScala
.toList shouldBe expectedTransactionsTrees
}
}
behavior of "8.6 TransactionClient.getTransactionsTrees"
it should "pass start offset, end offset, transaction filter and verbose flag with the request" in {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
val begin = new data.LedgerOffset.Absolute("1")
val end = new data.LedgerOffset.Absolute("2")
val transactionFilter = new data.FiltersByParty(
Map[String, data.Filter](
"Alice" -> data.InclusiveFilter.ofTemplateIds(
Set(
new data.Identifier("p1", "m1", "e1"),
new data.Identifier("p2", "m2", "e2"),
).asJava
)
).asJava
)
transactionClient
.getTransactionsTrees(begin, end, transactionFilter, true)
.toList()
.blockingGet()
val request = transactionService.lastTransactionsTreesRequest.get()
request.begin shouldBe Some(LedgerOffset(Absolute("1")))
request.end shouldBe Some(LedgerOffset(Absolute("2")))
val filter = request.filter.get.filtersByParty
filter.keySet shouldBe Set("Alice")
filter("Alice").inclusive.get.templateFilters.toSet shouldBe Set(
TemplateFilter(
Some(Identifier("p1", moduleName = "m1", entityName = "e1")),
includeCreatedEventBlob = false,
),
TemplateFilter(
Some(Identifier("p2", moduleName = "m2", entityName = "e2")),
includeCreatedEventBlob = false,
),
)
request.verbose shouldBe true
}
}
behavior of "8.7 TransactionClient.getTransactionsTrees"
it should "request stream with the correct ledger ID" in {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionsTrees(ledgerBegin, ledgerEnd, emptyFilter, false)
.toList()
.blockingGet()
transactionService.lastTransactionsTreesRequest
.get()
.ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "8.9 TransactionClient.getTransactionByEventId"
it should "look up transaction by event ID" ignore forAll(ledgerContentWithEventIdGen) {
case (ledgerContent, eventId, transactionTree) =>
ledgerServices.withTransactionsClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionByEventId(eventId, Set.empty[String].asJava)
.blockingGet() shouldBe transactionTree
transactionService.lastTransactionByEventIdRequest.get().eventId shouldBe eventId
}
}
behavior of "8.10 TransactionClient.getTransactionByEventId"
it should "pass the requesting parties with the request" ignore {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
val requestingParties = Set("Alice", "Bob")
transactionClient.getTransactionByEventId("eventId", requestingParties.asJava).blockingGet()
transactionService.lastTransactionByEventIdRequest
.get()
.requestingParties
.toSet shouldBe requestingParties
}
}
behavior of "8.11 TransactionClient.getTransactionByEventId"
it should "send the correct ledger ID with the request" ignore {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
transactionClient.getTransactionByEventId("eventId", Set.empty[String].asJava).blockingGet()
transactionService.lastTransactionByEventIdRequest
.get()
.ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "8.12 TransactionClient.getTransactionById"
it should "look up transaction by transaction ID" ignore forAll(
ledgerContentWithTransactionIdGen
) { case (ledgerContent, transactionId, transactionTree) =>
ledgerServices.withTransactionsClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionById(transactionId, Set.empty[String].asJava)
.blockingGet() shouldBe transactionTree
transactionService.lastTransactionByIdRequest.get().transactionId shouldBe transactionId
}
}
behavior of "8.13 TransactionClient.getTransactionById"
it should "pass the requesting parties with the request" ignore {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
val requestingParties = Set("Alice", "Bob")
transactionClient
.getTransactionById("transactionId", requestingParties.asJava)
.blockingGet()
transactionService.lastTransactionByIdRequest
.get()
.requestingParties
.toSet shouldBe requestingParties
}
}
behavior of "8.14 TransactionClient.getTransactionById"
it should "send the correct ledger ID with the request" ignore {
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionById("transactionId", Set.empty[String].asJava)
.blockingGet()
transactionService.lastTransactionByIdRequest
.get()
.ledgerId shouldBe ledgerServices.ledgerId
}
}
behavior of "8.15 TransactionClient.getLedgerEnd"
it should "provide ledger end from the ledger" in forAll(nonEmptyLedgerContent) {
case (ledgerContent, transactions) =>
ledgerServices.withTransactionsClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, _) =>
val expectedOffset = new data.LedgerOffset.Absolute(transactions.last.getOffset)
transactionClient.getLedgerEnd.blockingGet() shouldBe expectedOffset
}
}
it should "provide LEDGER_BEGIN from empty ledger" in
ledgerServices.withTransactionsClient(Observable.empty()) { (transactionClient, _) =>
transactionClient.getLedgerEnd.blockingGet() shouldBe
data.LedgerOffset.LedgerBegin.getInstance()
}
behavior of "8.15 TransactionClient.getLedgerEnd"
it should "request ledger end with correct ledger ID" in
ledgerServices.withTransactionsClient(Observable.empty()) {
(transactionClient, transactionService) =>
transactionClient.getLedgerEnd.blockingGet()
transactionService.lastLedgerEndRequest.get().ledgerId shouldBe ledgerServices.ledgerId
}
behavior of "Authentication"
def toAuthenticatedServer(fn: TransactionsClient => Any): Any =
ledgerServices.withTransactionsClient(Observable.empty(), mockedAuthService) { (client, _) =>
fn(client)
}
it should "deny access without a token" in {
withClue("getTransactions specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, ledgerEnd, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactions without specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionsTree specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactionsTrees(ledgerBegin, ledgerEnd, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionByEventId") {
expectUnauthenticated {
toAuthenticatedServer(_.getTransactionByEventId("...", Set(someParty).asJava).blockingGet())
}
}
withClue("getTransactionById") {
expectUnauthenticated {
toAuthenticatedServer(_.getTransactionById("...", Set(someParty).asJava).blockingGet())
}
}
withClue("getFlatTransactionByEventId") {
expectUnauthenticated {
toAuthenticatedServer(
_.getFlatTransactionByEventId("...", Set(someParty).asJava).blockingGet()
)
}
}
withClue("getFlatTransactionById") {
expectUnauthenticated {
toAuthenticatedServer(_.getFlatTransactionById("...", Set(someParty).asJava).blockingGet())
}
}
withClue("getLedgerEnd") {
expectUnauthenticated {
toAuthenticatedServer(_.getLedgerEnd.blockingGet())
}
}
}
it should "deny access with insufficient authorization" in {
withClue("getTransactions specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactions(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
someOtherPartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactions without specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false, someOtherPartyReadWriteToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionsTree specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionsTrees(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
someOtherPartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionByEventId") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionByEventId("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getTransactionById") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionById("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getFlatTransactionByEventId") {
expectPermissionDenied {
toAuthenticatedServer(
_.getFlatTransactionByEventId("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getFlatTransactionById") {
expectPermissionDenied {
toAuthenticatedServer(
_.getFlatTransactionById("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getLedgerEnd") {
expectUnauthenticated {
toAuthenticatedServer(_.getLedgerEnd(emptyToken).blockingGet())
}
}
}
it should "allow access with sufficient authorization" in {
withClue("getTransactions specifying end") {
toAuthenticatedServer(
_.getTransactions(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
somePartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactions without specifying end") {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false, somePartyReadWriteToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactionsTree specifying end") {
toAuthenticatedServer(
_.getTransactionsTrees(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
somePartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactionByEventId") {
toAuthenticatedServer(
_.getTransactionByEventId("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getTransactionById") {
toAuthenticatedServer(
_.getTransactionById("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getFlatTransactionByEventId") {
toAuthenticatedServer(
_.getFlatTransactionByEventId("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getFlatTransactionById") {
toAuthenticatedServer(
_.getFlatTransactionById("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getLedgerEnd") {
toAuthenticatedServer(_.getLedgerEnd(publicToken).blockingGet())
}
}
}

View File

@ -0,0 +1,428 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc
import java.util.concurrent.TimeUnit
import com.daml.ledger.javaapi.data
import com.daml.ledger.rxjava._
import com.daml.ledger.rxjava.grpc.helpers.TransactionGenerator._
import com.daml.ledger.rxjava.grpc.helpers.{DataLayerHelpers, LedgerServices, TestConfiguration}
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset.Value.Absolute
import com.daml.ledger.api.v1.transaction_filter.TemplateFilter
import com.daml.ledger.api.v1.value.Identifier
import io.reactivex.Observable
import org.scalacheck.Shrink
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec
import scala.jdk.CollectionConverters._
final class UpdateClientImplTest
extends AnyFlatSpec
with ScalaCheckDrivenPropertyChecks
with Matchers
with AuthMatchers
with DataLayerHelpers {
override val ledgerServices = new LedgerServices("update-service-ledger")
implicit def tupleNoShrink[A, B]: Shrink[(A, B)] = Shrink.shrinkAny
private val ledgerBegin = data.ParticipantOffsetV2.ParticipantBegin.getInstance()
private val ledgerEnd = data.ParticipantOffsetV2.ParticipantEnd.getInstance()
private val emptyFilter = new data.FiltersByPartyV2(Map.empty[String, data.Filter].asJava)
behavior of "8.1 TransactionClient.getTransactions"
it should "return transactions from the ledger" in forAll(ledgerContentGen) {
case (ledgerContent, expectedTransactions) =>
ledgerServices.withUpdateClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, _) =>
transactionClient
.getTransactions(ledgerBegin, ledgerEnd, emptyFilter, false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.toList shouldBe expectedTransactions
}
}
behavior of "8.2 TransactionClient.getTransactions"
it should "pass start offset, end offset, transaction filter and verbose flag with the request" in {
ledgerServices.withUpdateClient(Observable.empty()) { (transactionClient, transactionService) =>
val begin = new data.ParticipantOffsetV2.Absolute("1")
val end = new data.ParticipantOffsetV2.Absolute("2")
val transactionFilter = new data.FiltersByPartyV2(
Map[String, data.Filter](
"Alice" -> data.InclusiveFilter.ofTemplateIds(
Set(
new data.Identifier("p1", "m1", "e1"),
new data.Identifier("p2", "m2", "e2"),
).asJava
)
).asJava
)
transactionClient
.getTransactions(begin, end, transactionFilter, true)
.toList()
.blockingGet()
val request = transactionService.lastUpdatesRequest.get()
request.beginExclusive shouldBe Some(ParticipantOffset(Absolute("1")))
request.endInclusive shouldBe Some(ParticipantOffset(Absolute("2")))
val filter = request.filter.get.filtersByParty
filter.keySet shouldBe Set("Alice")
filter("Alice").inclusive.get.templateFilters.toSet shouldBe Set(
TemplateFilter(
Some(Identifier("p1", moduleName = "m1", entityName = "e1")),
includeCreatedEventBlob = false,
),
TemplateFilter(
Some(Identifier("p2", moduleName = "m2", entityName = "e2")),
includeCreatedEventBlob = false,
),
)
request.verbose shouldBe true
}
}
behavior of "8.5 TransactionClient.getTransactionsTrees"
it should "return transaction trees from the ledger" ignore forAll(ledgerContentTreeGen) {
case (ledgerContent, expectedTransactionsTrees) =>
ledgerServices.withUpdateClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, _) =>
transactionClient
.getTransactionsTrees(ledgerBegin, ledgerEnd, emptyFilter, false)
.blockingIterable()
.asScala
.toList shouldBe expectedTransactionsTrees
}
}
behavior of "8.6 TransactionClient.getTransactionsTrees"
it should "pass start offset, end offset, transaction filter and verbose flag with the request" in {
ledgerServices.withUpdateClient(Observable.empty()) { (transactionClient, transactionService) =>
val begin = new data.ParticipantOffsetV2.Absolute("1")
val end = new data.ParticipantOffsetV2.Absolute("2")
val transactionFilter = new data.FiltersByPartyV2(
Map[String, data.Filter](
"Alice" -> data.InclusiveFilter.ofTemplateIds(
Set(
new data.Identifier("p1", "m1", "e1"),
new data.Identifier("p2", "m2", "e2"),
).asJava
)
).asJava
)
transactionClient
.getTransactionsTrees(begin, end, transactionFilter, true)
.toList()
.blockingGet()
val request = transactionService.lastUpdatesTreesRequest.get()
request.beginExclusive shouldBe Some(ParticipantOffset(Absolute("1")))
request.endInclusive shouldBe Some(ParticipantOffset(Absolute("2")))
val filter = request.filter.get.filtersByParty
filter.keySet shouldBe Set("Alice")
filter("Alice").inclusive.get.templateFilters.toSet shouldBe Set(
TemplateFilter(
Some(Identifier("p1", moduleName = "m1", entityName = "e1")),
includeCreatedEventBlob = false,
),
TemplateFilter(
Some(Identifier("p2", moduleName = "m2", entityName = "e2")),
includeCreatedEventBlob = false,
),
)
request.verbose shouldBe true
}
}
behavior of "8.9 TransactionClient.getTransactionTreeByEventId"
it should "look up transaction by event ID" ignore forAll(ledgerContentWithEventIdGen) {
case (ledgerContent, eventId, transactionTree) =>
ledgerServices.withUpdateClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionTreeByEventId(eventId, Set.empty[String].asJava)
.blockingGet() shouldBe transactionTree
transactionService.lastTransactionTreeByEventIdRequest.get().eventId shouldBe eventId
}
}
behavior of "8.10 TransactionClient.getTransactionTreeByEventId"
it should "pass the requesting parties with the request" ignore {
ledgerServices.withUpdateClient(Observable.empty()) { (transactionClient, transactionService) =>
val requestingParties = Set("Alice", "Bob")
transactionClient
.getTransactionTreeByEventId("eventId", requestingParties.asJava)
.blockingGet()
transactionService.lastTransactionTreeByEventIdRequest
.get()
.requestingParties
.toSet shouldBe requestingParties
}
}
behavior of "8.12 TransactionClient.getTransactionTreeById"
it should "look up transaction by transaction ID" ignore forAll(
ledgerContentWithTransactionIdGen
) { case (ledgerContent, transactionId, transactionTree) =>
ledgerServices.withUpdateClient(Observable.fromIterable(ledgerContent.asJava)) {
(transactionClient, transactionService) =>
transactionClient
.getTransactionTreeById(transactionId, Set.empty[String].asJava)
.blockingGet() shouldBe transactionTree
transactionService.lastTransactionTreeByIdRequest.get().updateId shouldBe transactionId
}
}
behavior of "8.13 TransactionClient.getTransactionTreeById"
it should "pass the requesting parties with the request" ignore {
ledgerServices.withUpdateClient(Observable.empty()) { (transactionClient, transactionService) =>
val requestingParties = Set("Alice", "Bob")
transactionClient
.getTransactionTreeById("transactionId", requestingParties.asJava)
.blockingGet()
transactionService.lastTransactionTreeByIdRequest
.get()
.requestingParties
.toSet shouldBe requestingParties
}
}
behavior of "Authentication"
def toAuthenticatedServer(fn: UpdateClient => Any): Any =
ledgerServices.withUpdateClient(Observable.empty(), mockedAuthService) { (client, _) =>
fn(client)
}
it should "deny access without a token" in {
withClue("getTransactions specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, ledgerEnd, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactions without specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionsTree specifying end") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactionsTrees(ledgerBegin, ledgerEnd, filterFor(someParty), false)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionTreeByEventId") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactionTreeByEventId("...", Set(someParty).asJava).blockingGet()
)
}
}
withClue("getTransactionTreeById") {
expectUnauthenticated {
toAuthenticatedServer(_.getTransactionTreeById("...", Set(someParty).asJava).blockingGet())
}
}
withClue("getTransactionByEventId") {
expectUnauthenticated {
toAuthenticatedServer(
_.getTransactionByEventId("...", Set(someParty).asJava).blockingGet()
)
}
}
withClue("getTransactionById") {
expectUnauthenticated {
toAuthenticatedServer(_.getTransactionById("...", Set(someParty).asJava).blockingGet())
}
}
}
it should "deny access with insufficient authorization" in {
withClue("getTransactions specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactions(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
someOtherPartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactions without specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false, someOtherPartyReadWriteToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionsTree specifying end") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionsTrees(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
someOtherPartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
}
withClue("getTransactionTreeByEventId") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionTreeByEventId("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getTransactionTreeById") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionTreeById("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getTransactionByEventId") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionByEventId("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
withClue("getTransactionById") {
expectPermissionDenied {
toAuthenticatedServer(
_.getTransactionById("...", Set(someParty).asJava, someOtherPartyReadWriteToken)
.blockingGet()
)
}
}
}
it should "allow access with sufficient authorization" in {
withClue("getTransactions specifying end") {
toAuthenticatedServer(
_.getTransactions(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
somePartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactions without specifying end") {
toAuthenticatedServer(
_.getTransactions(ledgerBegin, filterFor(someParty), false, somePartyReadWriteToken)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactionsTree specifying end") {
toAuthenticatedServer(
_.getTransactionsTrees(
ledgerBegin,
ledgerEnd,
filterFor(someParty),
false,
somePartyReadWriteToken,
)
.timeout(TestConfiguration.timeoutInSeconds, TimeUnit.SECONDS)
.blockingIterable()
.asScala
.size
)
}
withClue("getTransactionTreeByEventId") {
toAuthenticatedServer(
_.getTransactionTreeByEventId("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getTransactionTreeById") {
toAuthenticatedServer(
_.getTransactionTreeById("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getTransactionByEventId") {
toAuthenticatedServer(
_.getTransactionByEventId("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
withClue("getTransactionById") {
toAuthenticatedServer(
_.getTransactionById("...", Set(someParty).asJava, somePartyReadWriteToken)
.blockingGet()
)
}
}
}

View File

@ -1,56 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.ActiveContractsServiceAuthorization
import com.daml.ledger.api.v1.active_contracts_service.ActiveContractsServiceGrpc.ActiveContractsService
import com.daml.ledger.api.v1.active_contracts_service.{
ActiveContractsServiceGrpc,
GetActiveContractsRequest,
GetActiveContractsResponse,
}
import io.grpc.ServerServiceDefinition
import io.grpc.stub.StreamObserver
import io.reactivex.disposables.Disposable
import io.reactivex.{Observable, Observer}
import scala.concurrent.ExecutionContext
final class ActiveContractsServiceImpl(
getActiveContractsResponses: Observable[GetActiveContractsResponse]
) extends ActiveContractsService
with FakeAutoCloseable {
private var lastRequest = Option.empty[GetActiveContractsRequest]
override def getActiveContracts(
request: GetActiveContractsRequest,
responseObserver: StreamObserver[GetActiveContractsResponse],
): Unit = {
lastRequest = Option(request)
getActiveContractsResponses.subscribe(new Observer[GetActiveContractsResponse] {
override def onSubscribe(d: Disposable): Unit = ()
override def onNext(t: GetActiveContractsResponse): Unit = responseObserver.onNext(t)
override def onError(e: Throwable): Unit = responseObserver.onError(e)
override def onComplete(): Unit = responseObserver.onCompleted()
})
}
def getLastRequest: Option[GetActiveContractsRequest] = this.lastRequest
}
object ActiveContractsServiceImpl {
/** Return the ServerServiceDefinition and the underlying ActiveContractsServiceImpl for inspection */
def createWithRef(
getActiveContractsResponses: Observable[GetActiveContractsResponse],
authorizer: Authorizer,
)(implicit ec: ExecutionContext): (ServerServiceDefinition, ActiveContractsServiceImpl) = {
val impl = new ActiveContractsServiceImpl(getActiveContractsResponses)
val authImpl = new ActiveContractsServiceAuthorization(impl, authorizer)
(ActiveContractsServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -4,22 +4,20 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.CommandCompletionServiceAuthorization
import com.daml.ledger.api.v1.command_completion_service.CommandCompletionServiceGrpc.CommandCompletionService
import com.daml.ledger.api.v1.command_completion_service._
import com.digitalasset.canton.ledger.api.auth.services.CommandCompletionServiceV2Authorization
import com.daml.ledger.api.v2.command_completion_service.CommandCompletionServiceGrpc.CommandCompletionService
import com.daml.ledger.api.v2.command_completion_service._
import io.grpc.ServerServiceDefinition
import io.grpc.stub.StreamObserver
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.ExecutionContext
final class CommandCompletionServiceImpl(
completions: List[CompletionStreamResponse],
end: CompletionEndResponse,
completions: List[CompletionStreamResponse]
) extends CommandCompletionService
with FakeAutoCloseable {
private var lastCompletionStreamRequest: Option[CompletionStreamRequest] = None
private var lastCompletionEndRequest: Option[CompletionEndRequest] = None
override def completionStream(
request: CompletionStreamRequest,
@ -29,24 +27,17 @@ final class CommandCompletionServiceImpl(
completions.foreach(responseObserver.onNext)
}
override def completionEnd(request: CompletionEndRequest): Future[CompletionEndResponse] = {
this.lastCompletionEndRequest = Some(request)
Future.successful(end)
}
def getLastCompletionStreamRequest: Option[CompletionStreamRequest] =
this.lastCompletionStreamRequest
def getLastCompletionEndRequest: Option[CompletionEndRequest] = this.lastCompletionEndRequest
}
object CommandCompletionServiceImpl {
def createWithRef(
completions: List[CompletionStreamResponse],
end: CompletionEndResponse,
authorizer: Authorizer,
)(implicit ec: ExecutionContext): (ServerServiceDefinition, CommandCompletionServiceImpl) = {
val impl = new CommandCompletionServiceImpl(completions, end)
val authImpl = new CommandCompletionServiceAuthorization(impl, authorizer)
val impl = new CommandCompletionServiceImpl(completions)
val authImpl = new CommandCompletionServiceV2Authorization(impl, authorizer)
(CommandCompletionServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -4,9 +4,9 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.CommandServiceAuthorization
import com.daml.ledger.api.v1.command_service.CommandServiceGrpc.CommandService
import com.daml.ledger.api.v1.command_service._
import com.digitalasset.canton.ledger.api.auth.services.CommandServiceV2Authorization
import com.daml.ledger.api.v2.command_service.CommandServiceGrpc.CommandService
import com.daml.ledger.api.v2.command_service._
import com.google.protobuf.empty.Empty
import io.grpc.ServerServiceDefinition
@ -14,7 +14,7 @@ import scala.concurrent.{ExecutionContext, Future}
final class CommandServiceImpl(
submitAndWaitResponse: Future[Empty],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForTransactionIdResponse],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForUpdateIdResponse],
submitAndWaitForTransactionResponse: Future[SubmitAndWaitForTransactionResponse],
submitAndWaitForTransactionTreeResponse: Future[SubmitAndWaitForTransactionTreeResponse],
) extends CommandService
@ -27,9 +27,9 @@ final class CommandServiceImpl(
submitAndWaitResponse
}
override def submitAndWaitForTransactionId(
override def submitAndWaitForUpdateId(
request: SubmitAndWaitRequest
): Future[SubmitAndWaitForTransactionIdResponse] = {
): Future[SubmitAndWaitForUpdateIdResponse] = {
this.lastRequest = Some(request)
submitAndWaitForTransactionIdResponse
}
@ -55,7 +55,7 @@ object CommandServiceImpl {
def createWithRef(
submitAndWaitResponse: Future[Empty],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForTransactionIdResponse],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForUpdateIdResponse],
submitAndWaitForTransactionResponse: Future[SubmitAndWaitForTransactionResponse],
submitAndWaitForTransactionTreeResponse: Future[SubmitAndWaitForTransactionTreeResponse],
authorizer: Authorizer,
@ -66,7 +66,7 @@ object CommandServiceImpl {
submitAndWaitForTransactionResponse,
submitAndWaitForTransactionTreeResponse,
)
val authImpl = new CommandServiceAuthorization(impl, authorizer)
val authImpl = new CommandServiceV2Authorization(impl, authorizer)
(CommandServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -4,38 +4,44 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.CommandSubmissionServiceAuthorization
import com.daml.ledger.api.v1.command_submission_service.CommandSubmissionServiceGrpc.CommandSubmissionService
import com.daml.ledger.api.v1.command_submission_service.{
import com.digitalasset.canton.ledger.api.auth.services.CommandSubmissionServiceV2Authorization
import com.daml.ledger.api.v2.command_submission_service.CommandSubmissionServiceGrpc.CommandSubmissionService
import com.daml.ledger.api.v2.command_submission_service.{
CommandSubmissionServiceGrpc,
SubmitReassignmentRequest,
SubmitReassignmentResponse,
SubmitRequest,
SubmitResponse,
}
import com.google.protobuf.empty.Empty
import io.grpc.ServerServiceDefinition
import scala.concurrent.{ExecutionContext, Future}
final class CommandSubmissionServiceImpl(getResponse: () => Future[Empty])
final class CommandSubmissionServiceImpl(getResponse: () => Future[SubmitResponse])
extends CommandSubmissionService
with FakeAutoCloseable {
@volatile private var submittedRequest: Option[SubmitRequest] = None
override def submit(request: SubmitRequest): Future[Empty] = {
override def submit(request: SubmitRequest): Future[SubmitResponse] = {
this.submittedRequest = Some(request)
getResponse()
}
def getSubmittedRequest: Option[SubmitRequest] = submittedRequest
override def submitReassignment(
request: SubmitReassignmentRequest
): Future[SubmitReassignmentResponse] = Future.failed(new UnsupportedOperationException())
}
object CommandSubmissionServiceImpl {
def createWithRef(getResponse: () => Future[Empty], authorizer: Authorizer)(implicit
def createWithRef(getResponse: () => Future[SubmitResponse], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, CommandSubmissionServiceImpl) = {
val impl = new CommandSubmissionServiceImpl(getResponse)
val authImpl = new CommandSubmissionServiceAuthorization(impl, authorizer)
val authImpl = new CommandSubmissionServiceV2Authorization(impl, authorizer)
(CommandSubmissionServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -6,12 +6,9 @@ package com.daml.ledger.rxjava.grpc.helpers
import java.util.Optional
import com.daml.ledger.javaapi.data._
import com.daml.ledger.api.v1.active_contracts_service.GetActiveContractsResponse
import com.daml.ledger.api.v1.command_completion_service.CompletionEndResponse
import com.daml.ledger.api.v1.event.CreatedEvent
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset.Value.Absolute
import com.daml.ledger.api.v1.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.state_service.{ActiveContract, GetActiveContractsResponse}
import com.daml.ledger.api.v2.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.state_service.GetActiveContractsResponse.ContractEntry
import com.google.protobuf.timestamp.Timestamp
import scala.jdk.CollectionConverters._
@ -24,7 +21,13 @@ trait DataLayerHelpers {
new GetActiveContractsResponse(
"",
"workflowId",
Seq[CreatedEvent](),
ContractEntry.ActiveContract(
new ActiveContract(
createdEvent = TransactionGenerator.createdEventGen.sample.map(_._1.value),
domainId = "someDomain",
reassignmentCounter = 0,
)
),
)
}
@ -44,16 +47,11 @@ trait DataLayerHelpers {
commands.asJava,
)
}
def genLedgerOffset(absVal: String): LedgerOffset =
new LedgerOffset(Absolute(absVal))
def genCompletionEndResponse(absVal: String): CompletionEndResponse =
new CompletionEndResponse(Some(genLedgerOffset(absVal)))
val filterNothing: FiltersByPartyV2 = new FiltersByPartyV2(Map[String, Filter]().asJava)
val filterNothing: FiltersByParty = new FiltersByParty(Map[String, Filter]().asJava)
def filterFor(party: String): FiltersByParty =
new FiltersByParty(
def filterFor(party: String): FiltersByPartyV2 =
new FiltersByPartyV2(
Map(party -> (InclusiveFilter.ofTemplateIds(Set.empty[Identifier].asJava): Filter)).asJava
)
}

View File

@ -3,22 +3,24 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.daml.ledger.api.v1.event_query_service.GetEventsByContractIdRequest
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.EventQueryServiceAuthorization
import com.daml.ledger.api.v1.event_query_service.EventQueryServiceGrpc.EventQueryService
import com.daml.ledger.api.v1.event_query_service._
import com.digitalasset.canton.ledger.api.auth.services.EventQueryServiceV2Authorization
import com.daml.ledger.api.v2.event_query_service.EventQueryServiceGrpc.EventQueryService
import com.daml.ledger.api.v2.event_query_service.{
EventQueryServiceGrpc,
GetEventsByContractIdResponse,
}
import io.grpc.ServerServiceDefinition
import scala.concurrent.{ExecutionContext, Future}
final class EventQueryServiceImpl(
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse],
getEventsByContractKeyResponse: Future[GetEventsByContractKeyResponse],
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse]
) extends EventQueryService
with FakeAutoCloseable {
private var lastGetEventsByContractIdRequest: Option[GetEventsByContractIdRequest] = None
private var lastGetEventsByContractKeyRequest: Option[GetEventsByContractKeyRequest] = None
override def getEventsByContractId(
request: GetEventsByContractIdRequest
@ -27,28 +29,18 @@ final class EventQueryServiceImpl(
getEventsByContractIdResponse
}
override def getEventsByContractKey(
request: GetEventsByContractKeyRequest
): Future[GetEventsByContractKeyResponse] = {
this.lastGetEventsByContractKeyRequest = Some(request)
getEventsByContractKeyResponse
}
def getLastGetEventsByContractIdRequest: Option[GetEventsByContractIdRequest] =
this.lastGetEventsByContractIdRequest
def getLastGetEventsByContractKeyRequest: Option[GetEventsByContractKeyRequest] =
this.lastGetEventsByContractKeyRequest
}
object EventQueryServiceImpl {
def createWithRef(
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse],
getEventsByContractKeyResponse: Future[GetEventsByContractKeyResponse],
authorizer: Authorizer,
)(implicit ec: ExecutionContext): (ServerServiceDefinition, EventQueryServiceImpl) = {
val impl =
new EventQueryServiceImpl(getEventsByContractIdResponse, getEventsByContractKeyResponse)
val authImpl = new EventQueryServiceAuthorization(impl, authorizer)
new EventQueryServiceImpl(getEventsByContractIdResponse)
val authImpl = new EventQueryServiceV2Authorization(impl, authorizer)
(EventQueryServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -1,44 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.LedgerConfigurationServiceAuthorization
import com.daml.ledger.api.v1.ledger_configuration_service.LedgerConfigurationServiceGrpc.LedgerConfigurationService
import com.daml.ledger.api.v1.ledger_configuration_service.{
GetLedgerConfigurationRequest,
GetLedgerConfigurationResponse,
LedgerConfigurationServiceGrpc,
}
import io.grpc.ServerServiceDefinition
import io.grpc.stub.StreamObserver
import scala.concurrent.ExecutionContext
class LedgerConfigurationServiceImpl(responses: Seq[GetLedgerConfigurationResponse])
extends LedgerConfigurationService
with FakeAutoCloseable {
private var lastRequest: Option[GetLedgerConfigurationRequest] = None
override def getLedgerConfiguration(
request: GetLedgerConfigurationRequest,
responseObserver: StreamObserver[GetLedgerConfigurationResponse],
): Unit = {
this.lastRequest = Some(request)
responses.foreach(responseObserver.onNext)
}
def getLastRequest: Option[GetLedgerConfigurationRequest] = this.lastRequest
}
object LedgerConfigurationServiceImpl {
def createWithRef(responses: Seq[GetLedgerConfigurationResponse], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, LedgerConfigurationServiceImpl) = {
val impl = new LedgerConfigurationServiceImpl(responses)
val authImpl = new LedgerConfigurationServiceAuthorization(impl, authorizer)
(LedgerConfigurationServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -1,45 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.LedgerIdentityServiceAuthorization
import com.daml.ledger.api.v1.ledger_identity_service.LedgerIdentityServiceGrpc.LedgerIdentityService
import com.daml.ledger.api.v1.ledger_identity_service.{
GetLedgerIdentityRequest,
GetLedgerIdentityResponse,
LedgerIdentityServiceGrpc,
}
import io.grpc.ServerServiceDefinition
import scala.annotation.nowarn
import scala.concurrent.{ExecutionContext, Future}
final class LedgerIdentityServiceImpl private (getResponse: () => Future[String])(implicit
ec: ExecutionContext
) extends LedgerIdentityService
with FakeAutoCloseable {
@nowarn("cat=deprecation&origin=com\\.daml\\.ledger\\.api\\.v1\\.ledger_identity_service\\..*")
override def getLedgerIdentity(
request: GetLedgerIdentityRequest
): Future[GetLedgerIdentityResponse] = {
getResponse().map(ledgerId => GetLedgerIdentityResponse(ledgerId))
}
}
object LedgerIdentityServiceImpl {
def createWithRef(getResponse: () => Future[String], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, LedgerIdentityServiceImpl) = {
val impl = new LedgerIdentityServiceImpl(
getResponse
)
val authImpl = new LedgerIdentityServiceAuthorization(impl, authorizer)
(LedgerIdentityServiceGrpc.bindService(authImpl, ec), impl): @nowarn(
"cat=deprecation&origin=com\\.daml\\.ledger\\.api\\.v1\\.ledger_identity_service\\..*"
)
}
}

View File

@ -9,13 +9,8 @@ import java.util.concurrent.TimeUnit
import org.apache.pekko.actor.ActorSystem
import com.daml.ledger.rxjava.grpc._
import com.daml.ledger.rxjava.grpc.helpers.TransactionsServiceImpl.LedgerItem
import com.daml.ledger.rxjava.{
CommandCompletionClient,
EventQueryClient,
LedgerConfigurationClient,
PackageClient,
}
import com.daml.ledger.rxjava.grpc.helpers.UpdateServiceImpl.LedgerItem
import com.daml.ledger.rxjava.{CommandCompletionClient, EventQueryClient, PackageClient}
import com.daml.grpc.adapter.{ExecutionSequencerFactory, SingleThreadExecutionSequencerPool}
import com.digitalasset.canton.ledger.api.auth.interceptor.{
AuthorizationInterceptor,
@ -27,27 +22,21 @@ import com.digitalasset.canton.ledger.api.auth.{
Authorizer,
ClaimSet,
}
import com.daml.ledger.api.v1.active_contracts_service.GetActiveContractsResponse
import com.daml.ledger.api.v1.command_completion_service.{
CompletionEndResponse,
CompletionStreamResponse,
}
import com.daml.ledger.api.v1.command_service.{
SubmitAndWaitForTransactionIdResponse,
import com.daml.ledger.api.v2.state_service.GetActiveContractsResponse
import com.daml.ledger.api.v2.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v2.command_service.{
SubmitAndWaitForTransactionResponse,
SubmitAndWaitForTransactionTreeResponse,
SubmitAndWaitForUpdateIdResponse,
}
import com.daml.ledger.api.v1.event_query_service.{
GetEventsByContractIdResponse,
GetEventsByContractKeyResponse,
}
import com.daml.ledger.api.v1.ledger_configuration_service.GetLedgerConfigurationResponse
import com.daml.ledger.api.v2.event_query_service.GetEventsByContractIdResponse
import com.daml.ledger.api.v1.package_service.{
GetPackageResponse,
GetPackageStatusResponse,
ListPackagesResponse,
}
import com.daml.ledger.api.v1.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.command_submission_service.SubmitResponse
import com.daml.tracing.NoOpTelemetry
import com.digitalasset.canton.logging.{LoggingContextWithTrace, NamedLoggerFactory}
import com.digitalasset.canton.ledger.localstore.InMemoryUserManagementStore
@ -59,19 +48,19 @@ import io.reactivex.Observable
import scala.concurrent.ExecutionContext.global
import scala.concurrent.{ExecutionContext, Future}
final class LedgerServices(val ledgerId: String) {
final class LedgerServices(val name: String) {
import LedgerServices._
val executionContext: ExecutionContext = global
private val esf: ExecutionSequencerFactory = new SingleThreadExecutionSequencerPool(ledgerId)
private val esf: ExecutionSequencerFactory = new SingleThreadExecutionSequencerPool(name)
private val pekkoSystem = ActorSystem("LedgerServicesParticipant")
private val participantId = "LedgerServicesParticipant"
private val loggerFactory = NamedLoggerFactory.root
val authorizer: Authorizer =
new Authorizer(
now = () => Clock.systemUTC().instant(),
ledgerId = ledgerId,
ledgerId = name,
participantId = participantId,
userManagementStore = new InMemoryUserManagementStore(createAdmin = false, loggerFactory),
ec = executionContext,
@ -149,15 +138,16 @@ final class LedgerServices(val ledgerId: String) {
def withACSClient(
getActiveContractsResponses: Observable[GetActiveContractsResponse],
ledgerContent: Observable[LedgerItem],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: (ActiveContractClientImpl, ActiveContractsServiceImpl) => Any): Any = {
)(f: (StateClientImpl, StateServiceImpl) => Any): Any = {
val (service, serviceImpl) =
ActiveContractsServiceImpl.createWithRef(getActiveContractsResponses, authorizer)(
StateServiceImpl.createWithRef(getActiveContractsResponses, ledgerContent, authorizer)(
executionContext
)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new ActiveContractClientImpl(ledgerId, channel, esf, accessToken), serviceImpl)
f(new StateClientImpl(channel, esf, accessToken), serviceImpl)
}
}
@ -167,11 +157,11 @@ final class LedgerServices(val ledgerId: String) {
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: TimeClientImpl => Any): Any =
withServerAndChannel(authService, services) { channel =>
f(new TimeClientImpl(ledgerId, channel, esf, accessToken))
f(new TimeClientImpl(channel, esf, accessToken))
}
def withCommandSubmissionClient(
getResponse: () => Future[Empty],
getResponse: () => Future[SubmitResponse],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
timeout: java.util.Optional[Duration] = java.util.Optional.empty[Duration],
@ -179,33 +169,30 @@ final class LedgerServices(val ledgerId: String) {
val (service, serviceImpl) =
CommandSubmissionServiceImpl.createWithRef(getResponse, authorizer)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new CommandSubmissionClientImpl(ledgerId, channel, accessToken, timeout), serviceImpl)
f(new CommandSubmissionClientImpl(channel, accessToken, timeout), serviceImpl)
}
}
def withCommandCompletionClient(
completions: List[CompletionStreamResponse],
end: CompletionEndResponse,
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: (CommandCompletionClient, CommandCompletionServiceImpl) => Any): Any = {
val (service, impl) =
CommandCompletionServiceImpl.createWithRef(completions, end, authorizer)(executionContext)
CommandCompletionServiceImpl.createWithRef(completions, authorizer)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new CommandCompletionClientImpl(ledgerId, channel, esf, accessToken), impl)
f(new CommandCompletionClientImpl(channel, esf, accessToken), impl)
}
}
def withEventQueryClient(
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse],
getEventsByContractKeyResponse: Future[GetEventsByContractKeyResponse],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: (EventQueryClient, EventQueryServiceImpl) => Any): Any = {
val (service, impl) =
EventQueryServiceImpl.createWithRef(
getEventsByContractIdResponse,
getEventsByContractKeyResponse,
authorizer,
)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
@ -228,13 +215,13 @@ final class LedgerServices(val ledgerId: String) {
authorizer,
)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new PackageClientImpl(ledgerId, channel, accessToken), impl)
f(new PackageClientImpl(channel, accessToken), impl)
}
}
def withCommandClient(
submitAndWaitResponse: Future[Empty],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForTransactionIdResponse],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForUpdateIdResponse],
submitAndWaitForTransactionResponse: Future[SubmitAndWaitForTransactionResponse],
submitAndWaitForTransactionTreeResponse: Future[SubmitAndWaitForTransactionTreeResponse],
authService: AuthService = AuthServiceWildcard,
@ -248,45 +235,19 @@ final class LedgerServices(val ledgerId: String) {
authorizer,
)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new CommandClientImpl(ledgerId, channel, accessToken), serviceImpl)
f(new CommandClientImpl(channel, accessToken), serviceImpl)
}
}
def withConfigurationClient(
responses: Seq[GetLedgerConfigurationResponse],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: (LedgerConfigurationClient, LedgerConfigurationServiceImpl) => Any): Any = {
val (service, impl) =
LedgerConfigurationServiceImpl.createWithRef(responses, authorizer)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new LedgerConfigurationClientImpl(ledgerId, channel, esf, accessToken), impl)
}
}
@deprecated("ledger identity service", since = "2.0.0")
def withLedgerIdentityClient(
getResponse: () => Future[String],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
timeout: java.util.Optional[Duration] = java.util.Optional.empty[Duration],
)(f: (LedgerIdentityClientImpl, LedgerIdentityServiceImpl) => Any): Any = {
val (service, serviceImpl) =
LedgerIdentityServiceImpl.createWithRef(getResponse, authorizer)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new LedgerIdentityClientImpl(channel, accessToken, timeout), serviceImpl)
}
}
def withTransactionsClient(
def withUpdateClient(
ledgerContent: Observable[LedgerItem],
authService: AuthService = AuthServiceWildcard,
accessToken: java.util.Optional[String] = java.util.Optional.empty[String],
)(f: (TransactionClientImpl, TransactionsServiceImpl) => Any): Any = {
)(f: (UpdateClientImpl, UpdateServiceImpl) => Any): Any = {
val (service, serviceImpl) =
TransactionsServiceImpl.createWithRef(ledgerContent, authorizer)(executionContext)
UpdateServiceImpl.createWithRef(ledgerContent, authorizer)(executionContext)
withServerAndChannel(authService, Seq(service)) { channel =>
f(new TransactionClientImpl(ledgerId, channel, esf, accessToken), serviceImpl)
f(new UpdateClientImpl(channel, esf, accessToken), serviceImpl)
}
}
@ -304,37 +265,30 @@ final class LedgerServices(val ledgerId: String) {
def withFakeLedgerServer(
getActiveContractsResponse: Observable[GetActiveContractsResponse],
transactions: Observable[LedgerItem],
commandSubmissionResponse: Future[Empty],
commandSubmissionResponse: Future[SubmitResponse],
completions: List[CompletionStreamResponse],
completionsEnd: CompletionEndResponse,
submitAndWaitResponse: Future[Empty],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForTransactionIdResponse],
submitAndWaitForUpdateIdResponse: Future[SubmitAndWaitForUpdateIdResponse],
submitAndWaitForTransactionResponse: Future[SubmitAndWaitForTransactionResponse],
submitAndWaitForTransactionTreeResponse: Future[SubmitAndWaitForTransactionTreeResponse],
getTimeResponses: List[GetTimeResponse],
getLedgerConfigurationResponses: Seq[GetLedgerConfigurationResponse],
getTimeResponse: Future[GetTimeResponse],
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse],
getEventsByContractKeyResponse: Future[GetEventsByContractKeyResponse],
listPackagesResponse: Future[ListPackagesResponse],
getPackageResponse: Future[GetPackageResponse],
getPackageStatusResponse: Future[GetPackageStatusResponse],
authService: AuthService,
)(f: (Server, LedgerServicesImpls) => Any): Any = {
val (services, impls) = LedgerServicesImpls.createWithRef(
Future.successful(ledgerId),
getActiveContractsResponse,
transactions,
commandSubmissionResponse,
completions,
completionsEnd,
submitAndWaitResponse,
submitAndWaitForTransactionIdResponse,
submitAndWaitForUpdateIdResponse,
submitAndWaitForTransactionResponse,
submitAndWaitForTransactionTreeResponse,
getTimeResponses,
getLedgerConfigurationResponses,
getTimeResponse,
getEventsByContractIdResponse,
getEventsByContractKeyResponse,
listPackagesResponse,
getPackageResponse,
getPackageStatusResponse,

View File

@ -4,27 +4,21 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.daml.ledger.api.v1.active_contracts_service.GetActiveContractsResponse
import com.daml.ledger.api.v1.command_completion_service.{
CompletionEndResponse,
CompletionStreamResponse,
}
import com.daml.ledger.api.v1.command_service.{
SubmitAndWaitForTransactionIdResponse,
import com.daml.ledger.api.v2.state_service.GetActiveContractsResponse
import com.daml.ledger.api.v2.command_completion_service.CompletionStreamResponse
import com.daml.ledger.api.v2.command_service.{
SubmitAndWaitForTransactionResponse,
SubmitAndWaitForTransactionTreeResponse,
SubmitAndWaitForUpdateIdResponse,
}
import com.daml.ledger.api.v1.event_query_service.{
GetEventsByContractIdResponse,
GetEventsByContractKeyResponse,
}
import com.daml.ledger.api.v1.ledger_configuration_service.GetLedgerConfigurationResponse
import com.daml.ledger.api.v2.event_query_service.GetEventsByContractIdResponse
import com.daml.ledger.api.v1.package_service.{
GetPackageResponse,
GetPackageStatusResponse,
ListPackagesResponse,
}
import com.daml.ledger.api.v1.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.testing.time_service.GetTimeResponse
import com.daml.ledger.api.v2.command_submission_service.SubmitResponse
import com.google.protobuf.empty.Empty
import io.grpc.ServerServiceDefinition
import io.reactivex.Observable
@ -32,13 +26,11 @@ import io.reactivex.Observable
import scala.concurrent.{ExecutionContext, Future}
case class LedgerServicesImpls(
ledgerIdentityServiceImpl: LedgerIdentityServiceImpl,
activeContractsServiceImpl: ActiveContractsServiceImpl,
transactionServiceImpl: TransactionsServiceImpl,
stateServiceImpl: StateServiceImpl,
transactionServiceImpl: UpdateServiceImpl,
commandSubmissionServiceImpl: CommandSubmissionServiceImpl,
commandCompletionServiceImpl: CommandCompletionServiceImpl,
commandServiceImpl: CommandServiceImpl,
ledgerConfigurationServiceImpl: LedgerConfigurationServiceImpl,
timeServiceImpl: TimeServiceImpl,
eventQueryServiceImpl: EventQueryServiceImpl,
packageServiceImpl: PackageServiceImpl,
@ -47,50 +39,41 @@ case class LedgerServicesImpls(
object LedgerServicesImpls {
def createWithRef(
ledgerIdResponse: Future[String],
getActiveContractsResponse: Observable[GetActiveContractsResponse],
transactions: Observable[TransactionsServiceImpl.LedgerItem],
commandSubmissionResponse: Future[Empty],
transactions: Observable[UpdateServiceImpl.LedgerItem],
commandSubmissionResponse: Future[SubmitResponse],
completions: List[CompletionStreamResponse],
completionsEnd: CompletionEndResponse,
submitAndWaitResponse: Future[Empty],
submitAndWaitForTransactionIdResponse: Future[SubmitAndWaitForTransactionIdResponse],
submitAndWaitForUpdateIdResponse: Future[SubmitAndWaitForUpdateIdResponse],
submitAndWaitForTransactionResponse: Future[SubmitAndWaitForTransactionResponse],
submitAndWaitForTransactionTreeResponse: Future[SubmitAndWaitForTransactionTreeResponse],
getTimeResponses: List[GetTimeResponse],
getLedgerConfigurationResponses: Seq[GetLedgerConfigurationResponse],
getTimeResponse: Future[GetTimeResponse],
getEventsByContractIdResponse: Future[GetEventsByContractIdResponse],
getEventsByContractKeyResponse: Future[GetEventsByContractKeyResponse],
listPackagesResponse: Future[ListPackagesResponse],
getPackageResponse: Future[GetPackageResponse],
getPackageStatusResponse: Future[GetPackageStatusResponse],
authorizer: Authorizer,
)(implicit ec: ExecutionContext): (Seq[ServerServiceDefinition], LedgerServicesImpls) = {
val (iServiceDef, iService) =
LedgerIdentityServiceImpl.createWithRef(() => ledgerIdResponse, authorizer)(ec)
val (acsServiceDef, acsService) =
ActiveContractsServiceImpl.createWithRef(getActiveContractsResponse, authorizer)(ec)
val (stateServiceDef, stateService) =
StateServiceImpl.createWithRef(getActiveContractsResponse, transactions, authorizer)(ec)
val (tsServiceDef, tsService) =
TransactionsServiceImpl.createWithRef(transactions, authorizer)(ec)
UpdateServiceImpl.createWithRef(transactions, authorizer)(ec)
val (csServiceDef, csService) =
CommandSubmissionServiceImpl.createWithRef(() => commandSubmissionResponse, authorizer)(ec)
val (ccServiceDef, ccService) =
CommandCompletionServiceImpl.createWithRef(completions, completionsEnd, authorizer)(ec)
CommandCompletionServiceImpl.createWithRef(completions, authorizer)(ec)
val (cServiceDef, cService) = CommandServiceImpl.createWithRef(
submitAndWaitResponse,
submitAndWaitForTransactionIdResponse,
submitAndWaitForUpdateIdResponse,
submitAndWaitForTransactionResponse,
submitAndWaitForTransactionTreeResponse,
authorizer,
)(ec)
val (lcServiceDef, lcService) =
LedgerConfigurationServiceImpl.createWithRef(getLedgerConfigurationResponses, authorizer)(ec)
val (timeServiceDef, timeService) =
TimeServiceImpl.createWithRef(getTimeResponses, authorizer)(ec)
TimeServiceImpl.createWithRef(getTimeResponse, authorizer)(ec)
val (eventQueryServiceDef, eventQueryService) =
EventQueryServiceImpl.createWithRef(
getEventsByContractIdResponse,
getEventsByContractKeyResponse,
authorizer,
)(ec)
val (packageServiceDef, packageService) =
@ -102,25 +85,21 @@ object LedgerServicesImpls {
)(ec)
val services = Seq(
iServiceDef,
acsServiceDef,
stateServiceDef,
tsServiceDef,
csServiceDef,
ccServiceDef,
cServiceDef,
lcServiceDef,
timeServiceDef,
eventQueryServiceDef,
packageServiceDef,
)
val impls = new LedgerServicesImpls(
iService,
acsService,
stateService,
tsService,
csService,
ccService,
cService,
lcService,
timeService,
eventQueryService,
packageService,

View File

@ -3,10 +3,20 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.daml.ledger.api.v1.package_service.{
GetPackageResponse,
GetPackageStatusResponse,
ListPackagesResponse,
}
import com.daml.ledger.api.v2.package_service.{
GetPackageRequest,
GetPackageStatusRequest,
ListPackagesRequest,
PackageServiceGrpc,
}
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.PackageServiceAuthorization
import com.daml.ledger.api.v1.package_service.PackageServiceGrpc.PackageService
import com.daml.ledger.api.v1.package_service._
import com.digitalasset.canton.ledger.api.auth.services.PackageServiceV2Authorization
import com.daml.ledger.api.v2.package_service.PackageServiceGrpc.PackageService
import io.grpc.ServerServiceDefinition
import scala.concurrent.{ExecutionContext, Future}
@ -55,7 +65,7 @@ object PackageServiceImpl {
)(implicit ec: ExecutionContext): (ServerServiceDefinition, PackageServiceImpl) = {
val impl =
new PackageServiceImpl(listPackagesResponse, getPackageResponse, getPackageStatusResponse)
val authImpl = new PackageServiceAuthorization(impl, authorizer)
val authImpl = new PackageServiceV2Authorization(impl, authorizer)
(PackageServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -0,0 +1,88 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset.ParticipantBoundary.PARTICIPANT_BEGIN
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset.Value.{Absolute, Boundary}
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.StateServiceAuthorization
import com.daml.ledger.api.v2.state_service.StateServiceGrpc.StateService
import com.daml.ledger.api.v2.state_service.{
GetActiveContractsRequest,
GetActiveContractsResponse,
GetConnectedDomainsRequest,
GetConnectedDomainsResponse,
GetLatestPrunedOffsetsRequest,
GetLatestPrunedOffsetsResponse,
GetLedgerEndRequest,
GetLedgerEndResponse,
StateServiceGrpc,
}
import com.daml.ledger.rxjava.grpc.helpers.UpdateServiceImpl.LedgerItem
import io.grpc.ServerServiceDefinition
import io.grpc.stub.StreamObserver
import io.reactivex.disposables.Disposable
import io.reactivex.{Observable, Observer}
import scala.concurrent.{ExecutionContext, Future, Promise}
final class StateServiceImpl(
getActiveContractsResponses: Observable[GetActiveContractsResponse],
ledgerContent: Observable[LedgerItem],
) extends StateService
with FakeAutoCloseable {
private var lastRequest = Option.empty[GetActiveContractsRequest]
override def getActiveContracts(
request: GetActiveContractsRequest,
responseObserver: StreamObserver[GetActiveContractsResponse],
): Unit = {
lastRequest = Option(request)
getActiveContractsResponses.subscribe(new Observer[GetActiveContractsResponse] {
override def onSubscribe(d: Disposable): Unit = ()
override def onNext(t: GetActiveContractsResponse): Unit = responseObserver.onNext(t)
override def onError(e: Throwable): Unit = responseObserver.onError(e)
override def onComplete(): Unit = responseObserver.onCompleted()
})
}
def getLastRequest: Option[GetActiveContractsRequest] = this.lastRequest
override def getLedgerEnd(request: GetLedgerEndRequest): Future[GetLedgerEndResponse] = {
val promise = Promise[GetLedgerEndResponse]()
val result =
ledgerContent
.map[GetLedgerEndResponse](t =>
GetLedgerEndResponse(Option(ParticipantOffset(Absolute(t.offset))))
)
.last(GetLedgerEndResponse(Option(ParticipantOffset(Boundary(PARTICIPANT_BEGIN)))))
result.subscribe(promise.success _, promise.failure _)
promise.future
}
override def getConnectedDomains(
request: GetConnectedDomainsRequest
): Future[GetConnectedDomainsResponse] = ???
override def getLatestPrunedOffsets(
request: GetLatestPrunedOffsetsRequest
): Future[GetLatestPrunedOffsetsResponse] = ???
}
object StateServiceImpl {
/** Return the ServerServiceDefinition and the underlying ActiveContractsServiceImpl for inspection */
def createWithRef(
getActiveContractsResponses: Observable[GetActiveContractsResponse],
ledgerContent: Observable[LedgerItem],
authorizer: Authorizer,
)(implicit ec: ExecutionContext): (ServerServiceDefinition, StateServiceImpl) = {
val impl = new StateServiceImpl(getActiveContractsResponses, ledgerContent)
val authImpl = new StateServiceAuthorization(impl, authorizer)
(StateServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -4,9 +4,9 @@
package com.daml.ledger.rxjava.grpc.helpers
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.TimeServiceAuthorization
import com.daml.ledger.api.v1.testing.time_service.TimeServiceGrpc.TimeService
import com.daml.ledger.api.v1.testing.time_service.{
import com.digitalasset.canton.ledger.api.auth.services.TimeServiceV2Authorization
import com.daml.ledger.api.v2.testing.time_service.TimeServiceGrpc.TimeService
import com.daml.ledger.api.v2.testing.time_service.{
GetTimeRequest,
GetTimeResponse,
SetTimeRequest,
@ -14,11 +14,10 @@ import com.daml.ledger.api.v1.testing.time_service.{
}
import com.google.protobuf.empty.Empty
import io.grpc.ServerServiceDefinition
import io.grpc.stub.StreamObserver
import scala.concurrent.{ExecutionContext, Future};
import scala.concurrent.{ExecutionContext, Future}
final class TimeServiceImpl(getTimeResponses: Seq[GetTimeResponse])
final class TimeServiceImpl(getTimeResponse: Future[GetTimeResponse])
extends TimeService
with FakeAutoCloseable {
@ -26,12 +25,10 @@ final class TimeServiceImpl(getTimeResponses: Seq[GetTimeResponse])
private var lastSetTimeRequest: Option[SetTimeRequest] = None
override def getTime(
request: GetTimeRequest,
responseObserver: StreamObserver[GetTimeResponse],
): Unit = {
request: GetTimeRequest
): Future[GetTimeResponse] = {
this.lastGetTimeRequest = Some(request)
getTimeResponses.foreach(responseObserver.onNext)
responseObserver.onCompleted()
getTimeResponse
}
override def setTime(request: SetTimeRequest): Future[Empty] = {
@ -45,11 +42,11 @@ final class TimeServiceImpl(getTimeResponses: Seq[GetTimeResponse])
}
object TimeServiceImpl {
def createWithRef(getTimeResponses: Seq[GetTimeResponse], authorizer: Authorizer)(implicit
def createWithRef(getTimeResponse: Future[GetTimeResponse], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, TimeServiceImpl) = {
val impl = new TimeServiceImpl(getTimeResponses)
val authImpl = new TimeServiceAuthorization(impl, authorizer)
val impl = new TimeServiceImpl(getTimeResponse)
val authImpl = new TimeServiceV2Authorization(impl, authorizer)
(TimeServiceGrpc.bindService(authImpl, ec), impl)
}
}

View File

@ -9,18 +9,21 @@ import com.daml.ledger.api.v1.transaction.TreeEvent.Kind.Exercised
import com.daml.ledger.api.v1.value
import com.daml.ledger.api.v1.value.Value.Sum
import com.daml.ledger.api.v1.value.{Identifier, Record, RecordField, Value, Variant}
import com.daml.ledger.api.v1.trace_context.TraceContext
import com.daml.ledger.javaapi.data
import com.daml.ledger.rxjava.grpc.helpers.TransactionsServiceImpl.LedgerItem
import com.daml.ledger.rxjava.grpc.helpers.UpdateServiceImpl.LedgerItem
import com.google.protobuf.ByteString
import com.google.protobuf.empty.Empty
import com.google.protobuf.timestamp.{Timestamp => ScalaTimestamp}
import com.google.rpc.status.{Status => SStatus}
import com.google.rpc.{Status => JStatus}
import org.scalacheck.{Arbitrary, Gen, Shrink}
import java.time.Instant
import java.util
import java.util.Collections
import com.daml.ledger.javaapi.data.Utils
import scala.jdk.CollectionConverters._
import scala.jdk.OptionConverters._
@ -203,7 +206,7 @@ object TransactionGenerator {
(javaInterfaceId, statusOrRecord.left.map(_._2).map(_._2)),
)
private val createdEventGen: Gen[(Created, data.CreatedEvent)] = for {
val createdEventGen: Gen[(Created, data.CreatedEvent)] = for {
eventId <- nonEmptyId
contractId <- nonEmptyId
contractKey <- Gen.option(valueGen(0))
@ -312,62 +315,95 @@ object TransactionGenerator {
case (scalaEvent, javaEvent) => (List(scalaEvent), List(javaEvent).asJava)
}
val transactionGen: Gen[(LedgerItem, data.Transaction)] = for {
transactionId <- nonEmptyId
val transactionGen: Gen[(LedgerItem, data.TransactionV2)] = for {
updateId <- nonEmptyId
commandId <- nonEmptyId
workflowId <- nonEmptyId
(scalaTimestamp, javaTimestamp) <- timestampGen
(scalaEvents, javaEvents) <- eventsGen
offset <- Gen.numStr
domainId <- Gen.alphaNumStr
traceContext <- Gen.const(Utils.newProtoTraceContext("parent", "state"))
} yield (
LedgerItem(transactionId, commandId, workflowId, scalaTimestamp, scalaEvents, offset),
new data.Transaction(transactionId, commandId, workflowId, javaTimestamp, javaEvents, offset),
)
val transactionTreeGen: Gen[(LedgerItem, data.TransactionTree)] = for {
transactionId <- nonEmptyId
commandId <- nonEmptyId
workflowId <- nonEmptyId
(scalaTimestamp, javaTimestamp) <- timestampGen
(scalaEvents, javaEvents) <- eventsGen
offset <- Gen.numStr
} yield (
LedgerItem(transactionId, commandId, workflowId, scalaTimestamp, scalaEvents, offset),
new data.TransactionTree(
transactionId,
LedgerItem(
updateId,
commandId,
workflowId,
scalaTimestamp,
scalaEvents,
offset,
domainId,
TraceContext.fromJavaProto(traceContext),
),
new data.TransactionV2(
updateId,
commandId,
workflowId,
javaTimestamp,
Collections.emptyMap(),
Collections.emptyList(),
javaEvents,
offset,
domainId,
traceContext,
),
)
val ledgerContentGen: Gen[(List[LedgerItem], List[data.Transaction])] =
val transactionTreeGen: Gen[(LedgerItem, data.TransactionTreeV2)] = for {
updateId <- nonEmptyId
commandId <- nonEmptyId
workflowId <- nonEmptyId
(scalaTimestamp, javaTimestamp) <- timestampGen
(scalaEvents, javaEvents) <- eventsGen
offset <- Gen.numStr
domainId <- Gen.alphaNumStr
traceContext <- Gen.const(Utils.newProtoTraceContext("parent", "state"))
} yield (
LedgerItem(
updateId,
commandId,
workflowId,
scalaTimestamp,
scalaEvents,
offset,
domainId,
TraceContext.fromJavaProto(traceContext),
),
new data.TransactionTreeV2(
updateId,
commandId,
workflowId,
javaTimestamp,
offset,
Collections.emptyMap(),
Collections.emptyList(),
domainId,
traceContext,
),
)
val ledgerContentGen: Gen[(List[LedgerItem], List[data.TransactionV2])] =
Gen.listOf(transactionGen).map(_.unzip)
val ledgerContentTreeGen: Gen[(List[LedgerItem], List[data.TransactionTree])] =
val ledgerContentTreeGen: Gen[(List[LedgerItem], List[data.TransactionTreeV2])] =
Gen.listOf(transactionTreeGen).map(_.unzip)
val ledgerContentWithEventIdGen: Gen[(List[LedgerItem], String, data.TransactionTree)] = for {
val ledgerContentWithEventIdGen: Gen[(List[LedgerItem], String, data.TransactionTreeV2)] = for {
(arbitraryLedgerContent, _) <- ledgerContentTreeGen
(queriedLedgerContent, queriedTransaction) <- transactionTreeGen.suchThat(_._1.events.nonEmpty)
ledgerContent = arbitraryLedgerContent :+ queriedLedgerContent
eventIds = queriedLedgerContent.events.map(TransactionsServiceImpl.eventId)
eventIds = queriedLedgerContent.events.map(UpdateServiceImpl.eventId)
eventIdList <- Gen.pick(1, eventIds)
eventId = eventIdList.head
} yield (ledgerContent, eventId, queriedTransaction)
val ledgerContentWithTransactionIdGen: Gen[(List[LedgerItem], String, data.TransactionTree)] =
val ledgerContentWithTransactionIdGen: Gen[(List[LedgerItem], String, data.TransactionTreeV2)] =
for {
(arbitraryLedgerContent, _) <- ledgerContentTreeGen
(queriedLedgerContent, queriedTransaction) <- transactionTreeGen
ledgerContent = arbitraryLedgerContent :+ queriedLedgerContent
transactionId = queriedLedgerContent.transactionId
} yield (ledgerContent, transactionId, queriedTransaction)
updateId = queriedLedgerContent.updateId
} yield (ledgerContent, updateId, queriedTransaction)
val nonEmptyLedgerContent: Gen[(List[LedgerItem], List[data.Transaction])] =
val nonEmptyLedgerContent: Gen[(List[LedgerItem], List[data.TransactionV2])] =
Gen.nonEmptyListOf(transactionGen).map(_.unzip)
}

View File

@ -1,200 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import java.util.concurrent.atomic.AtomicReference
import com.daml.ledger.rxjava.grpc.helpers.TransactionsServiceImpl.{
LedgerItem,
ledgerOffsetOrdering,
}
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.TransactionServiceAuthorization
import com.daml.ledger.api.v1.event.Event
import com.daml.ledger.api.v1.event.Event.Event.{Archived, Created, Empty}
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset.LedgerBoundary.{
LEDGER_BEGIN,
LEDGER_END,
Unrecognized,
}
import com.daml.ledger.api.v1.ledger_offset.LedgerOffset.Value.{Absolute, Boundary}
import com.daml.ledger.api.v1.transaction.Transaction
import com.daml.ledger.api.v1.transaction_service.TransactionServiceGrpc.TransactionService
import com.daml.ledger.api.v1.transaction_service._
import com.google.protobuf.timestamp.Timestamp
import io.grpc.stub.StreamObserver
import io.grpc.{Metadata, ServerServiceDefinition, Status}
import io.reactivex.disposables.Disposable
import io.reactivex.{Observable, Observer}
import scala.concurrent.{ExecutionContext, Future, Promise}
final class TransactionsServiceImpl(ledgerContent: Observable[LedgerItem])
extends TransactionService
with FakeAutoCloseable {
val lastTransactionsRequest = new AtomicReference[GetTransactionsRequest]()
val lastTransactionsTreesRequest = new AtomicReference[GetTransactionsRequest]()
val lastTransactionByEventIdRequest = new AtomicReference[GetTransactionByEventIdRequest]()
val lastTransactionByIdRequest = new AtomicReference[GetTransactionByIdRequest]()
val lastFlatTransactionByEventIdRequest = new AtomicReference[GetTransactionByEventIdRequest]()
val lastFlatTransactionByIdRequest = new AtomicReference[GetTransactionByIdRequest]()
val lastLedgerEndRequest = new AtomicReference[GetLedgerEndRequest]()
val lastLatestPrunedOffsetsRequest = new AtomicReference[GetLatestPrunedOffsetsRequest]
override def getTransactions(
request: GetTransactionsRequest,
responseObserver: StreamObserver[GetTransactionsResponse],
): Unit = {
lastTransactionsRequest.set(request)
if (request.end.exists(end => ledgerOffsetOrdering.gt(request.getBegin, end))) {
val metadata = new Metadata()
metadata.put(
Metadata.Key.of("cause", Metadata.ASCII_STRING_MARSHALLER),
s"BEGIN should be strictly smaller than END. Found BEGIN '${request.getBegin}' and END '${request.getEnd}'",
)
responseObserver.onError(Status.INVALID_ARGUMENT.asRuntimeException(metadata))
} else {
ledgerContent.subscribe(new Observer[LedgerItem] {
override def onSubscribe(d: Disposable): Unit = ()
override def onNext(t: LedgerItem): Unit =
responseObserver.onNext(GetTransactionsResponse(List(t.toTransaction)))
override def onError(t: Throwable): Unit = responseObserver.onError(t)
override def onComplete(): Unit = responseObserver.onCompleted()
})
}
}
override def getTransactionTrees(
request: GetTransactionsRequest,
responseObserver: StreamObserver[GetTransactionTreesResponse],
): Unit = {
lastTransactionsTreesRequest.set(request)
responseObserver.onCompleted()
}
override def getTransactionByEventId(
request: GetTransactionByEventIdRequest
): Future[GetTransactionResponse] = {
lastTransactionByEventIdRequest.set(request)
Future.successful(new GetTransactionResponse(None)) // just a mock, not intended for consumption
}
override def getTransactionById(
request: GetTransactionByIdRequest
): Future[GetTransactionResponse] = {
lastTransactionByIdRequest.set(request)
Future.successful(new GetTransactionResponse(None)) // just a mock, not intended for consumption
}
override def getFlatTransactionByEventId(
request: GetTransactionByEventIdRequest
): Future[GetFlatTransactionResponse] = {
lastFlatTransactionByEventIdRequest.set(request)
Future.successful(
new GetFlatTransactionResponse(None)
) // just a mock, not intended for consumption
}
override def getFlatTransactionById(
request: GetTransactionByIdRequest
): Future[GetFlatTransactionResponse] = {
lastFlatTransactionByIdRequest.set(request)
Future.successful(
new GetFlatTransactionResponse(None)
) // just a mock, not intended for consumption
}
override def getLedgerEnd(request: GetLedgerEndRequest): Future[GetLedgerEndResponse] = {
lastLedgerEndRequest.set(request)
val promise = Promise[GetLedgerEndResponse]()
val result =
ledgerContent
.map[GetLedgerEndResponse](t =>
GetLedgerEndResponse(Option(LedgerOffset(Absolute(t.offset))))
)
.last(GetLedgerEndResponse(Option(LedgerOffset(Boundary(LEDGER_BEGIN)))))
result.subscribe(promise.success _, promise.failure _)
promise.future
}
override def getLatestPrunedOffsets(
request: GetLatestPrunedOffsetsRequest
): Future[GetLatestPrunedOffsetsResponse] = {
lastLatestPrunedOffsetsRequest.set(request)
Future.successful(
new GetLatestPrunedOffsetsResponse(None)
) // just a mock, not intended for consumption
}
}
object TransactionsServiceImpl {
final case class LedgerItem(
transactionId: String,
commandId: String,
workflowId: String,
effectiveAt: Timestamp,
events: Seq[Event],
offset: String,
) {
def toTransaction =
Transaction(
transactionId,
commandId,
workflowId,
Some(effectiveAt),
events,
offset,
)
}
def eventId(event: Event): String = event.event match {
case Archived(archivedEvent) => archivedEvent.eventId
case Created(createdEvent) => createdEvent.eventId
case Empty => ""
}
def createWithRef(ledgerContent: Observable[LedgerItem], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, TransactionsServiceImpl) = {
val impl = new TransactionsServiceImpl(ledgerContent)
val authImpl = new TransactionServiceAuthorization(impl, authorizer)
(TransactionServiceGrpc.bindService(authImpl, ec), impl)
}
val ledgerOffsetOrdering: Ordering[LedgerOffset] = (x: LedgerOffset, y: LedgerOffset) => {
if (x.equals(y)) 0
else {
x.getAbsolute match {
case "" =>
x.getBoundary match {
case LEDGER_BEGIN => -1
case LEDGER_END => 1
case Unrecognized(value) =>
throw new RuntimeException(
s"Found boundary that is neither BEGIN or END (value: $value)"
)
}
case xAbs =>
y.getAbsolute match {
case "" =>
y.getBoundary match {
case LEDGER_BEGIN => 1
case LEDGER_END => -1
case Unrecognized(value) =>
throw new RuntimeException(
s"Found boundary that is neither BEGIN or END (value: $value)"
)
}
case yAbs => xAbs.compareTo(yAbs)
}
}
}
}
}

View File

@ -0,0 +1,186 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.ledger.rxjava.grpc.helpers
import java.util.concurrent.atomic.AtomicReference
import com.daml.ledger.api.v1.trace_context.TraceContext
import com.daml.ledger.rxjava.grpc.helpers.UpdateServiceImpl.{LedgerItem, participantOffsetOrdering}
import com.digitalasset.canton.ledger.api.auth.Authorizer
import com.digitalasset.canton.ledger.api.auth.services.UpdateServiceAuthorization
import com.daml.ledger.api.v1.event.Event
import com.daml.ledger.api.v1.event.Event.Event.{Archived, Created, Empty}
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset
import com.daml.ledger.api.v2.participant_offset.ParticipantOffset.ParticipantBoundary.{
PARTICIPANT_BEGIN,
PARTICIPANT_END,
Unrecognized,
}
import com.daml.ledger.api.v2.transaction.Transaction
import com.daml.ledger.api.v2.update_service.UpdateServiceGrpc.UpdateService
import com.daml.ledger.api.v2.update_service._
import com.google.protobuf.timestamp.Timestamp
import io.grpc.stub.StreamObserver
import io.grpc.{Metadata, ServerServiceDefinition, Status}
import io.reactivex.disposables.Disposable
import io.reactivex.{Observable, Observer}
import scala.concurrent.{ExecutionContext, Future}
final class UpdateServiceImpl(ledgerContent: Observable[LedgerItem])
extends UpdateService
with FakeAutoCloseable {
val lastUpdatesRequest = new AtomicReference[GetUpdatesRequest]()
val lastUpdatesTreesRequest = new AtomicReference[GetUpdatesRequest]()
val lastTransactionTreeByEventIdRequest = new AtomicReference[GetTransactionByEventIdRequest]()
val lastTransactionTreeByIdRequest = new AtomicReference[GetTransactionByIdRequest]()
val lastTransactionByEventIdRequest = new AtomicReference[GetTransactionByEventIdRequest]()
val lastTransactionByIdRequest = new AtomicReference[GetTransactionByIdRequest]()
override def getUpdates(
request: GetUpdatesRequest,
responseObserver: StreamObserver[GetUpdatesResponse],
): Unit = {
lastUpdatesRequest.set(request)
if (
request.endInclusive
.exists(end => participantOffsetOrdering.gt(request.getBeginExclusive, end))
) {
val metadata = new Metadata()
metadata.put(
Metadata.Key.of("cause", Metadata.ASCII_STRING_MARSHALLER),
s"BEGIN should be strictly smaller than END. Found BEGIN '${request.getBeginExclusive}' and END '${request.getEndInclusive}'",
)
responseObserver.onError(Status.INVALID_ARGUMENT.asRuntimeException(metadata))
} else {
ledgerContent.subscribe(new Observer[LedgerItem] {
override def onSubscribe(d: Disposable): Unit = ()
override def onNext(t: LedgerItem): Unit =
responseObserver.onNext(
GetUpdatesResponse(GetUpdatesResponse.Update.Transaction(t.toTransaction))
)
override def onError(t: Throwable): Unit = responseObserver.onError(t)
override def onComplete(): Unit = responseObserver.onCompleted()
})
}
}
override def getUpdateTrees(
request: GetUpdatesRequest,
responseObserver: StreamObserver[GetUpdateTreesResponse],
): Unit = {
lastUpdatesTreesRequest.set(request)
responseObserver.onCompleted()
}
override def getTransactionTreeByEventId(
request: GetTransactionByEventIdRequest
): Future[GetTransactionTreeResponse] = {
lastTransactionTreeByEventIdRequest.set(request)
Future.successful(
new GetTransactionTreeResponse(None)
) // just a mock, not intended for consumption
}
override def getTransactionTreeById(
request: GetTransactionByIdRequest
): Future[GetTransactionTreeResponse] = {
lastTransactionTreeByIdRequest.set(request)
Future.successful(
new GetTransactionTreeResponse(None)
) // just a mock, not intended for consumption
}
override def getTransactionByEventId(
request: GetTransactionByEventIdRequest
): Future[GetTransactionResponse] = {
lastTransactionByEventIdRequest.set(request)
Future.successful(
new GetTransactionResponse(None)
) // just a mock, not intended for consumption
}
override def getTransactionById(
request: GetTransactionByIdRequest
): Future[GetTransactionResponse] = {
lastTransactionByIdRequest.set(request)
Future.successful(
new GetTransactionResponse(None)
) // just a mock, not intended for consumption
}
}
object UpdateServiceImpl {
final case class LedgerItem(
updateId: String,
commandId: String,
workflowId: String,
effectiveAt: Timestamp,
events: Seq[Event],
offset: String,
domainId: String,
traceContext: TraceContext,
) {
def toTransaction =
Transaction(
updateId,
commandId,
workflowId,
Some(effectiveAt),
events,
offset,
domainId,
Some(traceContext),
)
}
def eventId(event: Event): String = event.event match {
case Archived(archivedEvent) => archivedEvent.eventId
case Created(createdEvent) => createdEvent.eventId
case Empty => ""
}
def createWithRef(ledgerContent: Observable[LedgerItem], authorizer: Authorizer)(implicit
ec: ExecutionContext
): (ServerServiceDefinition, UpdateServiceImpl) = {
val impl = new UpdateServiceImpl(ledgerContent)
val authImpl = new UpdateServiceAuthorization(impl, authorizer)
(UpdateServiceGrpc.bindService(authImpl, ec), impl)
}
val participantOffsetOrdering: Ordering[ParticipantOffset] =
(x: ParticipantOffset, y: ParticipantOffset) => {
if (x.equals(y)) 0
else {
x.getAbsolute match {
case "" =>
x.getBoundary match {
case PARTICIPANT_BEGIN => -1
case PARTICIPANT_END => 1
case Unrecognized(value) =>
throw new RuntimeException(
s"Found boundary that is neither BEGIN or END (value: $value)"
)
}
case xAbs =>
y.getAbsolute match {
case "" =>
y.getBoundary match {
case PARTICIPANT_BEGIN => 1
case PARTICIPANT_END => -1
case Unrecognized(value) =>
throw new RuntimeException(
s"Found boundary that is neither BEGIN or END (value: $value)"
)
}
case yAbs => xAbs.compareTo(yAbs)
}
}
}
}
}