@@ -7,10 +7,10 @@ import com.digitalasset.canton.logging.{ErrorLoggingContext, NamedLoggerFactory,
77import com .digitalasset .canton .time .Clock
88import com .digitalasset .canton .tracing .{Spanning , TraceContext }
99import io .opentelemetry .api .trace .Tracer
10- import org .lfdecentralizedtrust .splice .codegen .java .splice .api .token .metadatav1 .AnyContract
1110import org .lfdecentralizedtrust .splice .codegen .java .splice .api .token .metadatav1
1211import org .lfdecentralizedtrust .splice .environment .DarResources
1312import org .lfdecentralizedtrust .splice .scan .store .ScanStore
13+ import org .lfdecentralizedtrust .splice .scan .util
1414import org .lfdecentralizedtrust .splice .util .{AmuletConfigSchedule , Contract }
1515import org .lfdecentralizedtrust .tokenstandard .allocationinstruction .v1
1616import org .lfdecentralizedtrust .tokenstandard .allocationinstruction .v1 .definitions
@@ -30,6 +30,8 @@ class HttpTokenStandardAllocationInstructionHandler(
3030 with Spanning
3131 with NamedLogging {
3232
33+ import HttpTokenStandardAllocationInstructionHandler .*
34+
3335 private val workflowId = this .getClass.getSimpleName
3436
3537 override def getAllocationFactory (respond : v1.Resource .GetAllocationFactoryResponse .type )(
@@ -50,78 +52,80 @@ class HttpTokenStandardAllocationInstructionHandler(
5052 .asRuntimeException()
5153 )
5254 )
55+ // TODO(#3630) Don't include amulet rules and newest open round when informees all have vetted the newest version.
56+ externalPartyConfigStateO <- store.lookupLatestExternalPartyConfigState()
5357 } yield {
5458 val activeSynchronizerId =
5559 AmuletConfigSchedule (amuletRules.payload.configSchedule)
5660 .getConfigAsOf(now)
5761 .decentralizedSynchronizer
5862 .activeSynchronizer
5963 val excludeDebugFields = body.excludeDebugFields.getOrElse(false )
64+ val choiceContextBuilder = new ChoiceContextBuilder (
65+ activeSynchronizerId,
66+ excludeDebugFields,
67+ )
6068 v1.Resource .GetAllocationFactoryResponseOK (
6169 definitions.FactoryWithChoiceContext (
6270 externalPartyAmuletRules.contractId.contractId,
63- definitions.ChoiceContext (
64- choiceContextData = io.circe.parser
65- .parse(
66- new metadatav1.ChoiceContext (
67- Map (
68- " amulet-rules" -> amuletRules.contractId.contractId,
69- " open-round" -> newestOpenRound.contractId.contractId,
70- ).map[String , metadatav1.AnyValue ] { case (k, v) =>
71- k -> new metadatav1.anyvalue.AV_ContractId (new AnyContract .ContractId (v))
72- }.asJava
73- ).toJson
74- )
75- .getOrElse(
76- throw new IllegalArgumentException (" Just-serialized JSON cannot be parsed." )
77- ),
78- disclosedContracts = Vector (
79- toTokenStandardDisclosedContract(
80- externalPartyAmuletRules.contract,
81- activeSynchronizerId,
82- excludeDebugFields,
83- ),
84- toTokenStandardDisclosedContract(
85- amuletRules,
86- activeSynchronizerId,
87- excludeDebugFields,
88- ),
89- toTokenStandardDisclosedContract(
90- newestOpenRound.contract,
91- activeSynchronizerId,
92- excludeDebugFields,
93- ),
94- ),
95- ),
71+ choiceContextBuilder
72+ .addContracts(
73+ " amulet-rules" -> amuletRules,
74+ " open-round" -> newestOpenRound.contract,
75+ )
76+ .addOptionalContract(" external-party-config-state" -> externalPartyConfigStateO)
77+ .disclose(externalPartyAmuletRules.contract)
78+ .build(),
9679 )
9780 )
9881 }
9982 }
10083 }
84+ }
85+
86+ object HttpTokenStandardAllocationInstructionHandler {
87+ final class ChoiceContextBuilder (activeSynchronizerId : String , excludeDebugFields : Boolean )(
88+ implicit elc : ErrorLoggingContext
89+ ) extends util.ChoiceContextBuilder [
90+ definitions.DisclosedContract ,
91+ definitions.ChoiceContext ,
92+ ChoiceContextBuilder ,
93+ ](activeSynchronizerId, excludeDebugFields) {
10194
102- // The HTTP definition of the standard differs from any other
103- private def toTokenStandardDisclosedContract [TCId , T ](
104- contract : Contract [TCId , T ],
105- synchronizerId : String ,
106- excludeDebugFields : Boolean ,
107- )(implicit elc : ErrorLoggingContext ): definitions.DisclosedContract = {
108- val asHttp = contract.toHttp
109- definitions.DisclosedContract (
110- templateId = asHttp.templateId,
111- contractId = asHttp.contractId,
112- createdEventBlob = asHttp.createdEventBlob,
113- synchronizerId = synchronizerId,
114- debugPackageName =
115- if (excludeDebugFields) None
116- else
117- DarResources
118- .lookupPackageId(contract.identifier.getPackageId)
119- .map(_.metadata.name),
120- debugPayload = if (excludeDebugFields) None else Some (asHttp.payload),
121- debugCreatedAt =
122- if (excludeDebugFields) None
123- else Some (contract.createdAt.atOffset(ZoneOffset .UTC )),
95+ def build (): definitions.ChoiceContext = definitions.ChoiceContext (
96+ choiceContextData = io.circe.parser
97+ .parse(
98+ new metadatav1.ChoiceContext (contextEntries.asJava).toJson
99+ )
100+ .getOrElse(
101+ throw new RuntimeException (" Just-serialized JSON cannot be parsed." )
102+ ),
103+ disclosedContracts = disclosedContracts.toVector,
124104 )
125- }
126105
106+ // The HTTP definition of the standard differs from any other
107+ override protected def toTokenStandardDisclosedContract [TCId , T ](
108+ contract : Contract [TCId , T ],
109+ synchronizerId : String ,
110+ excludeDebugFields : Boolean ,
111+ ): definitions.DisclosedContract = {
112+ val asHttp = contract.toHttp
113+ definitions.DisclosedContract (
114+ templateId = asHttp.templateId,
115+ contractId = asHttp.contractId,
116+ createdEventBlob = asHttp.createdEventBlob,
117+ synchronizerId = synchronizerId,
118+ debugPackageName =
119+ if (excludeDebugFields) None
120+ else
121+ DarResources
122+ .lookupPackageId(contract.identifier.getPackageId)
123+ .map(_.metadata.name),
124+ debugPayload = if (excludeDebugFields) None else Some (asHttp.payload),
125+ debugCreatedAt =
126+ if (excludeDebugFields) None
127+ else Some (contract.createdAt.atOffset(ZoneOffset .UTC )),
128+ )
129+ }
130+ }
127131}
0 commit comments