daml_json/
request.rs

1use crate::data::{DamlJsonCreatedEvent, DamlJsonExerciseResult, DamlJsonParty};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::collections::HashMap;
5use std::iter::once;
6
7/// Daml JSON API request metadata.
8#[derive(Debug, Serialize, Deserialize)]
9pub struct DamlJsonRequestMeta {
10    #[serde(rename = "commandId")]
11    pub command_id: String,
12}
13
14impl DamlJsonRequestMeta {
15    pub fn new(command_id: impl Into<String>) -> Self {
16        Self {
17            command_id: command_id.into(),
18        }
19    }
20}
21
22/// Daml JSON API create contract request.
23#[derive(Debug, Serialize, Deserialize)]
24pub struct DamlJsonCreateRequest {
25    #[serde(rename = "templateId")]
26    pub template_id: String,
27    pub payload: Value,
28    pub meta: Option<DamlJsonRequestMeta>,
29}
30
31impl DamlJsonCreateRequest {
32    /// Create a new `DamlJsonCreateRequest` for a given template id and contract payload.
33    pub fn new(template_id: impl Into<String>, payload: Value) -> Self {
34        Self {
35            template_id: template_id.into(),
36            payload,
37            meta: None,
38        }
39    }
40
41    /// Create a new `DamlJsonCreateRequest` with metadata for a given template id and contract payload.
42    pub fn new_with_meta(template_id: impl Into<String>, payload: Value, meta: DamlJsonRequestMeta) -> Self {
43        Self {
44            template_id: template_id.into(),
45            payload,
46            meta: Some(meta),
47        }
48    }
49}
50
51/// Daml JSON API create contract response.
52#[derive(Debug, Serialize, Deserialize)]
53pub struct DamlJsonCreateResponse {
54    pub status: u16,
55    pub result: DamlJsonCreatedEvent,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub warnings: Option<HashMap<String, Vec<String>>>,
58}
59
60/// Represents either a Daml JSON API [`DamlJsonExerciseRequest`] or [`DamlJsonExerciseByKeyRequest`].
61///
62/// This is required as the Daml JSON API uses the same path (`exercise`) for both request types and the only way
63/// to uniquely identify which case we have been provided is by checking for the `contractId` and `key` fields.
64///
65/// To avoid having to first convert to a generic JSON `Value` to decide check which structure has been provided we
66/// use the `serde` [untagged enum](https://serde.rs/enum-representations.html#untagged) feature and add an
67/// [`DamlJsonInvalidExerciseRequest`] variant which has both `contractId` and `key` fields.  This allow the downstream
68/// handier to rejected the request with a suitable error message.
69#[derive(Debug, Serialize, Deserialize)]
70#[serde(untagged)]
71pub enum DamlJsonExerciseRequestType {
72    Invalid(DamlJsonInvalidExerciseRequest),
73    Exercise(DamlJsonExerciseRequest),
74    ExerciseByKey(DamlJsonExerciseByKeyRequest),
75}
76
77/// Daml JSON API exercise choice request.
78#[derive(Debug, Serialize, Deserialize)]
79pub struct DamlJsonExerciseRequest {
80    #[serde(rename = "templateId")]
81    pub template_id: String,
82    #[serde(rename = "contractId")]
83    pub contract_id: String,
84    pub choice: String,
85    pub argument: Value,
86}
87
88impl DamlJsonExerciseRequest {
89    /// Create a new `DamlJsonExerciseRequest` for a given template id, contract id, choice name and choice arguments.
90    pub fn new(
91        template_id: impl Into<String>,
92        contract_id: impl Into<String>,
93        choice: impl Into<String>,
94        argument: Value,
95    ) -> Self {
96        Self {
97            template_id: template_id.into(),
98            contract_id: contract_id.into(),
99            choice: choice.into(),
100            argument,
101        }
102    }
103}
104
105/// Daml JSON API exercise choice response.
106#[derive(Debug, Serialize, Deserialize)]
107pub struct DamlJsonExerciseResponse {
108    pub status: u16,
109    pub result: DamlJsonExerciseResult,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub warnings: Option<HashMap<String, Vec<String>>>,
112}
113
114/// Daml JSON API exercise choice by key request.
115#[derive(Debug, Serialize, Deserialize)]
116pub struct DamlJsonExerciseByKeyRequest {
117    #[serde(rename = "templateId")]
118    pub template_id: String,
119    pub key: Value,
120    pub choice: String,
121    pub argument: Value,
122}
123
124impl DamlJsonExerciseByKeyRequest {
125    /// Create a new `DamlJsonExerciseByKeyRequest` for a given template id, contract key, choice name and choice
126    /// arguments.
127    pub fn new(template_id: impl Into<String>, key: Value, choice: impl Into<String>, argument: Value) -> Self {
128        Self {
129            template_id: template_id.into(),
130            key,
131            choice: choice.into(),
132            argument,
133        }
134    }
135}
136
137/// Daml JSON API exercise choice by key response.
138#[derive(Debug, Serialize, Deserialize)]
139pub struct DamlJsonExerciseByKeyResponse {
140    pub status: u16,
141    pub result: DamlJsonExerciseResult,
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub warnings: Option<HashMap<String, Vec<String>>>,
144}
145
146/// An invalid Daml JSON API exercise choice request (`key` and `contractId` are mutually exclusive).
147///
148/// See [`DamlJsonExerciseRequestType`] for details.
149#[derive(Debug, Serialize, Deserialize)]
150pub struct DamlJsonInvalidExerciseRequest {
151    #[serde(rename = "templateId")]
152    pub template_id: String,
153    #[serde(rename = "contractId")]
154    pub contract_id: String,
155    pub key: Value,
156    pub choice: String,
157    pub argument: Value,
158}
159
160/// Daml JSON API create contract and exercise choice request.
161#[derive(Debug, Serialize, Deserialize)]
162pub struct DamlJsonCreateAndExerciseRequest {
163    #[serde(rename = "templateId")]
164    pub template_id: String,
165    pub payload: Value,
166    pub choice: String,
167    pub argument: Value,
168}
169
170impl DamlJsonCreateAndExerciseRequest {
171    /// Create a new `DamlJsonCreateAndExerciseRequest` for a given template id, payload, choice name and choice
172    /// arguments.
173    pub fn new(template_id: impl Into<String>, payload: Value, choice: impl Into<String>, argument: Value) -> Self {
174        Self {
175            template_id: template_id.into(),
176            payload,
177            choice: choice.into(),
178            argument,
179        }
180    }
181}
182
183/// Daml JSON API create contract and exercise choice response.
184#[derive(Debug, Serialize, Deserialize)]
185pub struct DamlJsonCreateAndExerciseResponse {
186    pub status: u16,
187    pub result: DamlJsonExerciseResult,
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub warnings: Option<HashMap<String, Vec<String>>>,
190}
191
192/// Daml JSON API fetch contract by id request.
193#[derive(Debug, Serialize, Deserialize)]
194pub struct DamlJsonFetchRequest {
195    #[serde(rename = "contractId")]
196    pub contract_id: String,
197}
198
199impl DamlJsonFetchRequest {
200    /// Create a new `DamlJsonFetchRequest` for a given contract id.
201    pub fn new(contract_id: impl Into<String>) -> Self {
202        Self {
203            contract_id: contract_id.into(),
204        }
205    }
206}
207
208/// Daml JSON API fetch contract by id response.
209#[derive(Debug, Serialize, Deserialize)]
210pub struct DamlJsonFetchResponse {
211    pub status: u16,
212    pub result: DamlJsonCreatedEvent,
213    #[serde(skip_serializing_if = "Option::is_none")]
214    pub warnings: Option<HashMap<String, Vec<String>>>,
215}
216
217/// Daml JSON API fetch contract by key request.
218#[derive(Debug, Serialize, Deserialize)]
219pub struct DamlJsonFetchByKeyRequest {
220    #[serde(rename = "templateId")]
221    pub template_id: String,
222    pub key: Value,
223}
224
225impl DamlJsonFetchByKeyRequest {
226    /// Create a new `DamlJsonFetchByKeyRequest` for a given template id and key.
227    pub fn new(template_id: impl Into<String>, key: Value) -> Self {
228        Self {
229            template_id: template_id.into(),
230            key,
231        }
232    }
233}
234
235/// Daml JSON API fetch contract by key response.
236#[derive(Debug, Serialize, Deserialize)]
237pub struct DamlJsonFetchByKeyResponse {
238    pub status: u16,
239    pub result: DamlJsonCreatedEvent,
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub warnings: Option<HashMap<String, Vec<String>>>,
242}
243
244/// Daml JSON API query response.
245#[derive(Debug, Serialize, Deserialize)]
246pub struct DamlJsonQueryResponse {
247    pub status: u16,
248    pub result: Vec<DamlJsonCreatedEvent>,
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub warnings: Option<HashMap<String, Vec<String>>>,
251}
252
253/// Daml JSON API fetch parties request.
254#[derive(Debug, Serialize, Deserialize)]
255pub struct DamlJsonFetchPartiesRequest(pub Vec<String>);
256
257impl DamlJsonFetchPartiesRequest {
258    /// Create a new `DamlJsonFetchPartiesRequest` for a given list of party identifiers.
259    pub fn new(identifiers: Vec<String>) -> Self {
260        Self(identifiers)
261    }
262}
263
264/// Daml JSON API fetch parties response.
265#[derive(Debug, Serialize, Deserialize)]
266pub struct DamlJsonFetchPartiesResponse {
267    pub status: u16,
268    pub result: Vec<DamlJsonParty>,
269    #[serde(skip_serializing_if = "Option::is_none")]
270    pub warnings: Option<HashMap<String, Vec<String>>>,
271}
272
273/// Daml JSON API allocate party request.
274#[derive(Debug, Serialize, Deserialize)]
275pub struct DamlJsonAllocatePartyRequest {
276    #[serde(rename = "identifierHint")]
277    pub identifier_hint: Option<String>,
278    #[serde(rename = "displayName")]
279    pub display_name: Option<String>,
280}
281
282impl DamlJsonAllocatePartyRequest {
283    /// Create a new `DamlJsonAllocatePartyRequest` with optional identifier hint & display name.
284    pub fn new<S: Into<String>>(identifier_hint: Option<S>, display_name: Option<S>) -> Self {
285        Self {
286            identifier_hint: identifier_hint.map(Into::into),
287            display_name: display_name.map(Into::into),
288        }
289    }
290}
291
292/// Daml JSON API allocate party response.
293#[derive(Debug, Serialize, Deserialize)]
294pub struct DamlJsonAllocatePartyResponse {
295    pub status: u16,
296    pub result: DamlJsonParty,
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub warnings: Option<HashMap<String, Vec<String>>>,
299}
300
301/// Daml JSON API list packages response.
302#[derive(Debug, Serialize, Deserialize)]
303pub struct DamlJsonListPackagesResponse {
304    pub status: u16,
305    pub result: Vec<String>,
306    #[serde(skip_serializing_if = "Option::is_none")]
307    pub warnings: Option<HashMap<String, Vec<String>>>,
308}
309
310/// Daml JSON API upload `Dar` response.
311#[derive(Debug, Serialize, Deserialize)]
312pub struct DamlJsonUploadDarResponse {
313    pub status: u16,
314    pub result: u8,
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub warnings: Option<HashMap<String, Vec<String>>>,
317}
318
319/// Daml JSON API generic error response.
320#[derive(Debug, Serialize, Deserialize)]
321pub struct DamlJsonErrorResponse {
322    pub status: u16,
323    pub errors: Vec<String>,
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub warnings: Option<HashMap<String, Vec<String>>>,
326}
327
328impl DamlJsonErrorResponse {
329    pub fn single(status: u16, error: String) -> Self {
330        Self {
331            status,
332            errors: vec![error],
333            warnings: None,
334        }
335    }
336}
337
338/// Make a warnings map with a single entry.
339pub fn make_single_warning(name: impl Into<String>, data: Vec<String>) -> HashMap<String, Vec<String>> {
340    once((name.into(), data)).collect::<HashMap<_, _>>()
341}