How to create User via gRPC

package examples.pingpong.grpc;

import java.util.Optional;
import java.util.UUID;

import com.daml.ledger.api.v1.CommandSubmissionServiceGrpc;
import com.daml.ledger.api.v1.CommandSubmissionServiceGrpc.CommandSubmissionServiceFutureStub;
import com.daml.ledger.api.v1.CommandSubmissionServiceOuterClass.SubmitRequest;
import com.daml.ledger.api.v1.CommandsOuterClass.Command;
import com.daml.ledger.api.v1.CommandsOuterClass.Commands;
import com.daml.ledger.api.v1.CommandsOuterClass.CreateCommand;
import com.daml.ledger.api.v1.LedgerIdentityServiceGrpc;
import com.daml.ledger.api.v1.LedgerIdentityServiceGrpc.LedgerIdentityServiceBlockingStub;
import com.daml.ledger.api.v1.LedgerIdentityServiceOuterClass.GetLedgerIdentityRequest;
import com.daml.ledger.api.v1.LedgerIdentityServiceOuterClass.GetLedgerIdentityResponse;
import com.daml.ledger.api.v1.ValueOuterClass.Identifier;
import com.daml.ledger.api.v1.ValueOuterClass.Record;
import com.daml.ledger.api.v1.ValueOuterClass.RecordField;
import com.daml.ledger.api.v1.ValueOuterClass.Value;
import com.daml.ledger.api.v1.admin.UserManagementServiceGrpc;
import com.daml.ledger.api.v1.admin.UserManagementServiceOuterClass;
import com.daml.ledger.api.v1.admin.UserManagementServiceGrpc.UserManagementServiceBlockingStub;
import com.daml.ledger.api.v1.admin.UserManagementServiceOuterClass.CreateUserResponse;
import com.daml.ledger.api.v1.admin.UserManagementServiceOuterClass.GetUserRequest;
import com.daml.ledger.api.v1.admin.UserManagementServiceOuterClass.GetUserResponse;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class PingPongGrpcMain {

// application id used for sending commands
public static final String APP_ID = "PingPongApp";

// constants for referring to the users with access to the parties
public static final String ALICE_USER = "alice";
public static final String BOB_USER = "bob";

public static void main(String[] args) {
    // Extract host and port from arguments
    if (args.length < 2) {
        System.err.println("Usage: HOST PORT [NUM_INITIAL_CONTRACTS]");
    String host = args[0];
    int port = Integer.parseInt(args[1]);

    // each party will create this number of initial Ping contracts
    int numInitialContracts = args.length == 3 ? Integer.parseInt(args[2]) : 10;

    // Initialize a plaintext gRPC channel
    ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();

    // fetch the ledger ID, which is used in subsequent requests sent to the ledger
    String ledgerId = fetchLedgerId(channel);

    // fetch the party IDs that got created in the Daml init script
    String aliceParty = fetchPartyId(channel, ALICE_USER);
    String bobParty = fetchPartyId(channel, BOB_USER);

    String packageId = Optional.ofNullable(System.getProperty(""))
            .orElseThrow(() -> new RuntimeException(" must be specified via sys properties"));

    Identifier pingIdentifier = Identifier.newBuilder()
    Identifier pongIdentifier = Identifier.newBuilder()

    // initialize the ping pong processors for Alice and Bob
    PingPongProcessor aliceProcessor = new PingPongProcessor(aliceParty, ledgerId, channel, pingIdentifier, pongIdentifier);
    PingPongProcessor bobProcessor = new PingPongProcessor(bobParty, ledgerId, channel, pingIdentifier, pongIdentifier);

    // start the processors asynchronously

    // send the initial commands for both parties
    createInitialContracts(channel, ledgerId, aliceParty, bobParty, pingIdentifier, numInitialContracts);
    createInitialContracts(channel, ledgerId, bobParty, aliceParty, pingIdentifier, numInitialContracts);

    try {
        // wait a couple of seconds for the processing to finish
    } catch (InterruptedException e) {

 * Creates numContracts number of Ping contracts. The sender is used as the submitting party.
 * @param channel        the gRPC channel to use for services
 * @param ledgerId       the previously fetched ledger id
 * @param sender         the party that sends the initial Ping contract
 * @param receiver       the party that receives the initial Ping contract
 * @param pingIdentifier the PingPong.Ping template identifier
 * @param numContracts   the number of initial contracts to create
private static void createInitialContracts(ManagedChannel channel, String ledgerId, String sender, String receiver, Identifier pingIdentifier, int numContracts) {
    CommandSubmissionServiceFutureStub submissionService = CommandSubmissionServiceGrpc.newFutureStub(channel);

    for (int i = 0; i < numContracts; i++) {
        // command that creates the initial Ping contract with the required parameters according to the model
        Command createCommand = Command.newBuilder().setCreate(
                                        // the identifier for a template's record is the same as the identifier for the template

        SubmitRequest submitRequest = SubmitRequest.newBuilder().setCommands(Commands.newBuilder()
                .setWorkflowId(String.format("Ping-%s-%d", sender, i))

        // asynchronously send the commands

 * Fetches the ledger id via the Ledger Identity Service.
 * @param channel the gRPC channel to use for services
 * @return the ledger id as provided by the ledger
private static String fetchLedgerId(ManagedChannel channel) {
    LedgerIdentityServiceBlockingStub ledgerIdService = LedgerIdentityServiceGrpc.newBlockingStub(channel);
    GetLedgerIdentityResponse identityResponse = ledgerIdService.getLedgerIdentity(GetLedgerIdentityRequest.getDefaultInstance());
    return identityResponse.getLedgerId();

private static String fetchPartyId(ManagedChannel channel, String userId) {
    UserManagementServiceBlockingStub userManagementService = UserManagementServiceGrpc.newBlockingStub(channel);
    GetUserResponse getUserResponse = userManagementService.getUser(GetUserRequest.newBuilder().setUserId(userId).build());
    return getUserResponse.getUser().getPrimaryParty();

 * @param channel
 * @param UserId
private static String createUser(ManagedChannel channel, String userId) {
    UserManagementServiceBlockingStub userManagementService = UserManagementServiceGrpc.newBlockingStub(channel);
    CreateUserRequest createUserRequest = userManagementService.createUser();
    GetUserResponse getUserResponse = userManagementService.getUser(GetUserRequest.newBuilder().setUserId(userId).build());
    // return getUserResponse.getUser().getPrimaryParty();
    return UserId;


Do you have a specific question about this or are you sharing your solution? In any case, I would probably recommend to remove the header that assigns the copyright to Digital Asset. :wink:

I noticed that the createUser method is not called anywhere in your code, is that on purpose? In any case, I would recommend you to have a look at the Java bindings, since they make it a lot less verbose to interact with the Ledger API than plain gRPC-generated code (and also allows you to take advantage of the codegen).

I am actually trying to make some method that createUser via gRPC. Do you have sample codes for it.?
I am trying to tweak this code but I could not find solution to make it.

What is failing specifically?

how to use this function CreateUserRequest Ledger API Reference — Daml SDK 2.5.3 documentation?

If you want to use the gRPC-generated code, my advice is to have a look at the gRPC docs first to get a sense of how the Protobuf API description whose documentation you pointed to. In your case specifically, you need at least to create a valid User object and pass it to the function. Note in the documentation when an object is required or optional and act accordingly. In order to enable backward-compatibility, Protobuf by itself doesn’t require any specific field to be there, even if that’s actually required for a request to be valid.

If you want to to avoid these problems altogether, I would again encourage you to use the Java bindings instead, which wrap the gRPC-generated code with some conveniences that allow you to not have to worry about these kind of things.