Not sure what I am doing wrong but I am getting the same security issue. I tried saving the contractId and exercising a choice. I am trying to exercise the AppInstallRequest_Accept
from the Quickstart using Pat 'user_pat_at_app-provider_dot_localhost::12202e0571cc7fc76ccc5cf4dd75f6cbdec6aeef12ee910f91b0c1ee90b692be00dc'
. Template id is '#quickstart-licensing:Licensing.AppInstall:AppInstallRequest
and contractId is 0065a1ebc5d46cd7a0eef88ea7f45d74b5a9af595c9d19624c0189c8fb9b36abfcca111220bb17772995efc66a839e82f14ff34be1abd1950813436f1e65ca798562b7cf62
Decoded token payload: {
exp: 1749716820,
iat: 1749716520,
jti: 'd754fd49-88b8-488f-9ba7-cfbc07d1db12',
iss: 'http://keycloak.localhost:8082/realms/AppProvider',
aud: [ 'https://canton.network.global', 'account' ],
sub: 'c87743ab-80e0-4b83-935a-4c0582226691',
typ: 'Bearer',
azp: 'app-provider-validator',
acr: '1',
'allowed-origins': [ '/*' ],
realm_access: {
roles: [
'offline_access',
'default-roles-quickstart',
'uma_authorization'
]
},
resource_access: { account: { roles: [Array] } },
scope: 'email profile',
clientHost: '192.168.65.1',
email_verified: false,
preferred_username: 'service-account-app-provider-validator',
clientAddress: '192.168.65.1',
client_id: 'app-provider-validator'
}
Token verified successfully
Failed to exercise choice: Error: Request failed with HTTP status code 401
Response body: {"code":"NA","cause":"A security-sensitive error has been received","correlationId":"52b1634b6cdfbdeaa997cf7e052e935e","traceId":"52b1634b6cdfbdeaa997cf7e052e935e","context":{},"resources":[],"errorCategory":-1,"grpcCodeValue":16,"retryInfo":null,"definiteAnswer":null}
at Function.exerciseChoice (/Users/paulwilkinson/projects/deploi/cn-quickstart/quickstart/deploi-server/src/services/providerLedger.service.ts:128:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /Users/paulwilkinson/projects/deploi/cn-quickstart/quickstart/deploi-server/src/routes/contracts.routes.ts:698:16
}
static async exerciseChoice(
contractId: string,
templateId: string,
choice: string,
choiceArgument: any,
providerPartyId: string
) {
const token = await TokenGenerator.generateProviderValidatorToken();
// Add meta and installMeta to choiceArgument if they don't exist
const enhancedChoiceArgument = {
...choiceArgument,
meta: {
values: [],
},
installMeta: {
values: [],
},
};
const command = {
commands: {
commands: [
{
ExerciseCommand: {
templateId,
contractId,
choice,
choiceArgument: enhancedChoiceArgument,
},
},
],
workflowId: `exercise-${choice}-${Date.now()}`,
applicationId: "92a520cb-2f09-4e55-b465-d178c6cfe5e4",
commandId: `exercise-${choice}-${Date.now()}`,
deduplicationPeriod: {
Empty: {},
},
actAs: [providerPartyId],
readAs: [providerPartyId],
submissionId: `exercise-${choice}`,
disclosedContracts: [],
domainId: "",
packageIdSelectionPreference: [],
},
transactionFormat: {
eventFormat: {
filtersByParty: {
[providerPartyId]: {},
},
verbose: true,
},
transactionShape: "TRANSACTION_SHAPE_LEDGER_EFFECTS",
},
};
try {
const response = await fetch(`${this.BASE_URL}/v2/commands/submit-and-wait-for-transaction`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify(command),
});
if (!response.ok) {
const responseBody = await response.text();
const errorDetails = JSON.parse(responseBody);
// Handle specific error cases
if (errorDetails.code === "INVALID_ARGUMENT") {
throw new Error(`Invalid template or choice: ${errorDetails.cause}`);
}
throw new Error(`Request failed with HTTP status code ${response.status}\nResponse body: ${responseBody}`);
}
return response.json();
} catch (error: any) {
// Enhance error message with more context
if (error.message.includes("Invalid template")) {
throw new Error(`Failed to exercise choice '${choice}' on contract ${contractId}: ${error.message}`);
}
throw error;
}
}
}