I am also working on our initial implementation and also can’t figure out how to get the contract id after creating the contract. Was wondering if you could point me in the right direction.
I am currently using the Ledger API v2, submit-and-wait
and am able to create the contract. I don’t know how to use the update id and completion offset to get the contract id.
I tried streaming events but it seems there are no js/ts packages for the 3.3-snapshot DSK. I also looked for an example but could only find Java examples.
I also tried using submit
, but I was getting 500 errors and no details.
I don’t think it makes sense to post source/errors as I don’t know if my approach is way off.
Cheers!
It looks like /v2/commands/submit-and-wait-for-transaction
includes the contract id(s) of the created contract(s).
Payload
{
"commands": {
"commandId": "command01",
"userId": "Alice",
"actAs": [ "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033" ],
"commands": [
{
"CreateCommand": {
"templateId": "#getcontractid:Main:Asset",
"createArguments": {
"issuer": "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"owner": "Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"name": "Asset 0001"
}
}
}
]
}
}
Response
{
"transaction": {
"updateId": "1220ebae900711ff06c1268db49d3824fe358af7f6b2869a41fe6f748f9c77aa074c",
"commandId": "command01",
"workflowId": "",
"effectiveAt": "2025-06-06T16:27:15.209058Z",
"events": [
{
"CreatedEvent": {
"offset": 44,
"nodeId": 0,
"contractId": "00909a0ed452ff5e50d1145bf23cd26d128a3f5075f6705cfb085560c64e10a1b0ca111220b0604df7ff4c6aaed636ca90bb384f0d1425cfd8985019d34f79801d41afb27d",
"templateId": "26dfa3676763576f3ec81b111337e5582d036eaae2bffba25bde72e0a061f974:Main:Asset",
"contractKey": null,
"createArgument": {
"issuer": "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"owner": "Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"name": "Asset 0001"
},
"createdEventBlob": "",
"interfaceViews": [],
"witnessParties": [
"Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"
],
"signatories": [
"Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"
],
"observers": [
"Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"
],
"createdAt": "2025-06-06T16:27:15.209058Z",
"packageName": "getcontractid"
}
}
],
"offset": 44,
"synchronizerId": "mysynchronizer::1220e7570b68dc555fb7d87ec9c679b2e0b6e1a6cea758d90cf2c3da43c4004d8849",
"traceContext": {
"traceparent": "00-6ea825d5051d6e6bc356b50ccbc3b938-068ae460e8f998e0-01",
"tracestate": null
},
"recordTime": "2025-06-06T16:27:15.325118Z"
}
}
1 Like
Do you have a link? I can’t find docs for submit-and-wait-for-transaction anywhere.
You can find it in the JSON Ledger API OpenAPI definition. But it may be easier and more illustrative to look at an example of creating a contract using JSON Ledger API.
1 Like
Thanks for this. I had not seen that documentation.
I tried their example and I’m not sure what I’m doing wrong.
I’m getting
Token verified successfully
Submitting body: {
"commands": {
"commandId": "command01",
"userId": "Alice",
"actAs": [
"Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"
],
"commands": [
{
"CreateCommand": {
"templateId": "#getcontractid:Main:Asset",
"createArguments": {
"issuer": "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"owner": "Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
"name": "Asset 0001"
}
}
}
]
}
}
Failed to create contract: Error: Request failed with HTTP status code 400
Response body: Invalid value for: body (Missing required field at 'transactionFormat')
at /Users/paulwilkinson/projects/deploi/cn-quickstart/quickstart/deploi-server/src/routes/contracts.routes.ts:118:15
at processTicksAndRejections (node:internal/process/task_queues:95:5)
Full error details: {
message: 'Request failed with HTTP status code 400\n' +
"Response body: Invalid value for: body (Missing required field at 'transactionFormat')",
code: undefined,
details: undefined,
stack: 'Error: Request failed with HTTP status code 400\n' +
"Response body: Invalid value for: body (Missing required field at 'transactionFormat')\n" +
' at /Users/paulwilkinson/projects/deploi/cn-quickstart/quickstart/deploi-server/src/routes/contracts.routes.ts:118:15\n' +
' at processTicksAndRejections (node:internal/process/task_queues:95:5)'
}
The code looks like this:
const example = {
commands: {
commandId: "command01",
userId: "Alice",
actAs: ["Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"],
commands: [
{
CreateCommand: {
templateId: "#getcontractid:Main:Asset",
createArguments: {
issuer: "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
owner: "Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
name: "Asset 0001",
},
},
},
],
},
};
const userToken = await TokenGenerator.generateUserValidatorToken();
console.log("Submitting body:", JSON.stringify(example, null, 2));
try {
const response = await fetch(`http://localhost:27575/v2/commands/submit-and-wait-for-transaction`, {
method: "POST",
headers: {
Authorization: `Bearer ${userToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(example),
});
if (!response.ok) {
const responseBody = await response.text();
throw new Error(`Request failed with HTTP status code ${response.status}\nResponse body: ${responseBody}`);
}
If I add a transactionFormat like this:
const example = {
actAs: ["Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033"],
userId: "app1", // Or "Alice::1220..." if that's your Keycloak user ID
commandId: "somecommandid2",
commands: [
{
CreateCommand: {
// <--- Direct command type as key
createArguments: {
// <--- Arguments under 'createArguments'
observers: [], // From their example
issuer: "Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033",
amount: "999.99",
currency: "USD",
owner: "Bob::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033", // Adjusted to your Bob ID
},
templateId: "#Main:Asset", // <--- Shorthand templateId
},
},
],
transactionFormat: {
eventFormat: {
filtersByParty: {
"Alice::1220f6829fc4e86f8f0632bfc4efb1887939828f4f48e9fd425239cefa4419ef5033": {},
},
verbose: true,
},
transactionShape: "TRANSACTION_SHAPE_ACS_DELTA",
},
};
then the error message seems to come from a bit deeper:
Full error details: {
message: 'Request failed with HTTP status code 400\n' +
"Response body: Invalid value for: body (Missing required field at 'commands.commands', Missing required field at 'commands.commandId', Missing required field at 'commands.actAs', JSON decoding to CNil should never happen at 'transactionShape')",
code: undefined,
details: undefined,
stack: 'Error: Request failed with HTTP status code 400\n' +
"Response body: Invalid value for: body (Missing required field at 'commands.commands', Missing required field at 'commands.commandId', Missing required field at 'commands.actAs', JSON decoding to CNil should never happen at 'transactionShape')\n" +
' at /Users/paulwilkinson/projects/deploi/cn-quickstart/quickstart/deploi-server/src/routes/contracts.routes.ts:129:15\n' +
' at processTicksAndRejections (node:internal/process/task_queues:95:5)'
}