Skip to main content

oanda_client/models/
variants.rs

1//! Tagged provider unions for orders and transactions.
2use super::*;
3use serde::{Deserialize, Serialize};
4
5/// Documented Order variants identified by OANDA’s `type` field.
6#[derive(Debug, Clone, PartialEq)]
7#[non_exhaustive]
8pub enum Order {
9    /// `MARKET` provider variant.
10    MarketOrder(MarketOrder),
11    /// `LIMIT` provider variant.
12    LimitOrder(LimitOrder),
13    /// `STOP` provider variant.
14    StopOrder(StopOrder),
15    /// `MARKET_IF_TOUCHED` provider variant.
16    MarketIfTouchedOrder(MarketIfTouchedOrder),
17    /// `TAKE_PROFIT` provider variant.
18    TakeProfitOrder(TakeProfitOrder),
19    /// `STOP_LOSS` provider variant.
20    StopLossOrder(StopLossOrder),
21    /// `GUARANTEED_STOP_LOSS` provider variant.
22    GuaranteedStopLossOrder(GuaranteedStopLossOrder),
23    /// `TRAILING_STOP_LOSS` provider variant.
24    TrailingStopLossOrder(TrailingStopLossOrder),
25    /// `FIXED_PRICE` provider variant.
26    FixedPriceOrder(FixedPriceOrder),
27    /// Future provider variant with its bounded raw value.
28    Unknown {
29        /// Provider discriminator.
30        kind: String,
31        /// Bounded provider object.
32        raw: serde_json::Value,
33    },
34}
35
36impl<'de> Deserialize<'de> for Order {
37    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
38        let value = serde_json::Value::deserialize(deserializer)?;
39        let kind = value
40            .get("type")
41            .and_then(serde_json::Value::as_str)
42            .ok_or_else(|| serde::de::Error::custom("missing OANDA type discriminator"))?;
43        match kind {
44            "MARKET" => serde_json::from_value(value)
45                .map(Self::MarketOrder)
46                .map_err(serde::de::Error::custom),
47            "LIMIT" => serde_json::from_value(value)
48                .map(Self::LimitOrder)
49                .map_err(serde::de::Error::custom),
50            "STOP" => serde_json::from_value(value)
51                .map(Self::StopOrder)
52                .map_err(serde::de::Error::custom),
53            "MARKET_IF_TOUCHED" => serde_json::from_value(value)
54                .map(Self::MarketIfTouchedOrder)
55                .map_err(serde::de::Error::custom),
56            "TAKE_PROFIT" => serde_json::from_value(value)
57                .map(Self::TakeProfitOrder)
58                .map_err(serde::de::Error::custom),
59            "STOP_LOSS" => serde_json::from_value(value)
60                .map(Self::StopLossOrder)
61                .map_err(serde::de::Error::custom),
62            "GUARANTEED_STOP_LOSS" => serde_json::from_value(value)
63                .map(Self::GuaranteedStopLossOrder)
64                .map_err(serde::de::Error::custom),
65            "TRAILING_STOP_LOSS" => serde_json::from_value(value)
66                .map(Self::TrailingStopLossOrder)
67                .map_err(serde::de::Error::custom),
68            "FIXED_PRICE" => serde_json::from_value(value)
69                .map(Self::FixedPriceOrder)
70                .map_err(serde::de::Error::custom),
71            other => Ok(Self::Unknown {
72                kind: other.to_owned(),
73                raw: value,
74            }),
75        }
76    }
77}
78
79impl Serialize for Order {
80    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
81        let (kind, mut value) = match self {
82            Self::MarketOrder(body) => (
83                "MARKET",
84                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
85            ),
86            Self::LimitOrder(body) => (
87                "LIMIT",
88                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
89            ),
90            Self::StopOrder(body) => (
91                "STOP",
92                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
93            ),
94            Self::MarketIfTouchedOrder(body) => (
95                "MARKET_IF_TOUCHED",
96                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
97            ),
98            Self::TakeProfitOrder(body) => (
99                "TAKE_PROFIT",
100                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
101            ),
102            Self::StopLossOrder(body) => (
103                "STOP_LOSS",
104                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
105            ),
106            Self::GuaranteedStopLossOrder(body) => (
107                "GUARANTEED_STOP_LOSS",
108                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
109            ),
110            Self::TrailingStopLossOrder(body) => (
111                "TRAILING_STOP_LOSS",
112                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
113            ),
114            Self::FixedPriceOrder(body) => (
115                "FIXED_PRICE",
116                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
117            ),
118            Self::Unknown { kind, raw } => (kind.as_str(), raw.clone()),
119        };
120        let object = value
121            .as_object_mut()
122            .ok_or_else(|| serde::ser::Error::custom("OANDA variant must be an object"))?;
123        object.insert(
124            "type".to_owned(),
125            serde_json::Value::String(kind.to_owned()),
126        );
127        value.serialize(serializer)
128    }
129}
130
131/// Documented OrderRequest variants identified by OANDA’s `type` field.
132#[derive(Debug, Clone, PartialEq)]
133#[non_exhaustive]
134pub enum OrderRequest {
135    /// `MARKET` provider variant.
136    MarketOrderRequest(MarketOrderRequest),
137    /// `LIMIT` provider variant.
138    LimitOrderRequest(LimitOrderRequest),
139    /// `STOP` provider variant.
140    StopOrderRequest(StopOrderRequest),
141    /// `MARKET_IF_TOUCHED` provider variant.
142    MarketIfTouchedOrderRequest(MarketIfTouchedOrderRequest),
143    /// `TAKE_PROFIT` provider variant.
144    TakeProfitOrderRequest(TakeProfitOrderRequest),
145    /// `STOP_LOSS` provider variant.
146    StopLossOrderRequest(StopLossOrderRequest),
147    /// `GUARANTEED_STOP_LOSS` provider variant.
148    GuaranteedStopLossOrderRequest(GuaranteedStopLossOrderRequest),
149    /// `TRAILING_STOP_LOSS` provider variant.
150    TrailingStopLossOrderRequest(TrailingStopLossOrderRequest),
151}
152
153impl<'de> Deserialize<'de> for OrderRequest {
154    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
155        let value = serde_json::Value::deserialize(deserializer)?;
156        let kind = value
157            .get("type")
158            .and_then(serde_json::Value::as_str)
159            .ok_or_else(|| serde::de::Error::custom("missing OANDA type discriminator"))?;
160        match kind {
161            "MARKET" => serde_json::from_value(value)
162                .map(Self::MarketOrderRequest)
163                .map_err(serde::de::Error::custom),
164            "LIMIT" => serde_json::from_value(value)
165                .map(Self::LimitOrderRequest)
166                .map_err(serde::de::Error::custom),
167            "STOP" => serde_json::from_value(value)
168                .map(Self::StopOrderRequest)
169                .map_err(serde::de::Error::custom),
170            "MARKET_IF_TOUCHED" => serde_json::from_value(value)
171                .map(Self::MarketIfTouchedOrderRequest)
172                .map_err(serde::de::Error::custom),
173            "TAKE_PROFIT" => serde_json::from_value(value)
174                .map(Self::TakeProfitOrderRequest)
175                .map_err(serde::de::Error::custom),
176            "STOP_LOSS" => serde_json::from_value(value)
177                .map(Self::StopLossOrderRequest)
178                .map_err(serde::de::Error::custom),
179            "GUARANTEED_STOP_LOSS" => serde_json::from_value(value)
180                .map(Self::GuaranteedStopLossOrderRequest)
181                .map_err(serde::de::Error::custom),
182            "TRAILING_STOP_LOSS" => serde_json::from_value(value)
183                .map(Self::TrailingStopLossOrderRequest)
184                .map_err(serde::de::Error::custom),
185            _ => Err(serde::de::Error::custom("unsupported OANDA request type")),
186        }
187    }
188}
189
190impl Serialize for OrderRequest {
191    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
192        let (kind, mut value) = match self {
193            Self::MarketOrderRequest(body) => (
194                "MARKET",
195                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
196            ),
197            Self::LimitOrderRequest(body) => (
198                "LIMIT",
199                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
200            ),
201            Self::StopOrderRequest(body) => (
202                "STOP",
203                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
204            ),
205            Self::MarketIfTouchedOrderRequest(body) => (
206                "MARKET_IF_TOUCHED",
207                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
208            ),
209            Self::TakeProfitOrderRequest(body) => (
210                "TAKE_PROFIT",
211                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
212            ),
213            Self::StopLossOrderRequest(body) => (
214                "STOP_LOSS",
215                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
216            ),
217            Self::GuaranteedStopLossOrderRequest(body) => (
218                "GUARANTEED_STOP_LOSS",
219                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
220            ),
221            Self::TrailingStopLossOrderRequest(body) => (
222                "TRAILING_STOP_LOSS",
223                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
224            ),
225        };
226        let object = value
227            .as_object_mut()
228            .ok_or_else(|| serde::ser::Error::custom("OANDA variant must be an object"))?;
229        object.insert(
230            "type".to_owned(),
231            serde_json::Value::String(kind.to_owned()),
232        );
233        value.serialize(serializer)
234    }
235}
236
237/// Documented Transaction variants identified by OANDA’s `type` field.
238#[derive(Debug, Clone, PartialEq)]
239#[non_exhaustive]
240#[expect(
241    clippy::large_enum_variant,
242    reason = "boxing a variant would change every caller's match; the stream already boxes the whole Transaction"
243)]
244pub enum Transaction {
245    /// `CREATE` provider variant.
246    CreateTransaction(CreateTransaction),
247    /// `CLOSE` provider variant.
248    CloseTransaction(CloseTransaction),
249    /// `REOPEN` provider variant.
250    ReopenTransaction(ReopenTransaction),
251    /// `CLIENT_CONFIGURE` provider variant.
252    ClientConfigureTransaction(ClientConfigureTransaction),
253    /// `CLIENT_CONFIGURE_REJECT` provider variant.
254    ClientConfigureRejectTransaction(ClientConfigureRejectTransaction),
255    /// `TRANSFER_FUNDS` provider variant.
256    TransferFundsTransaction(TransferFundsTransaction),
257    /// `TRANSFER_FUNDS_REJECT` provider variant.
258    TransferFundsRejectTransaction(TransferFundsRejectTransaction),
259    /// `MARKET_ORDER` provider variant.
260    MarketOrderTransaction(MarketOrderTransaction),
261    /// `MARKET_ORDER_REJECT` provider variant.
262    MarketOrderRejectTransaction(MarketOrderRejectTransaction),
263    /// `FIXED_PRICE_ORDER` provider variant.
264    FixedPriceOrderTransaction(FixedPriceOrderTransaction),
265    /// `LIMIT_ORDER` provider variant.
266    LimitOrderTransaction(LimitOrderTransaction),
267    /// `LIMIT_ORDER_REJECT` provider variant.
268    LimitOrderRejectTransaction(LimitOrderRejectTransaction),
269    /// `STOP_ORDER` provider variant.
270    StopOrderTransaction(StopOrderTransaction),
271    /// `STOP_ORDER_REJECT` provider variant.
272    StopOrderRejectTransaction(StopOrderRejectTransaction),
273    /// `MARKET_IF_TOUCHED_ORDER` provider variant.
274    MarketIfTouchedOrderTransaction(MarketIfTouchedOrderTransaction),
275    /// `MARKET_IF_TOUCHED_ORDER_REJECT` provider variant.
276    MarketIfTouchedOrderRejectTransaction(MarketIfTouchedOrderRejectTransaction),
277    /// `TAKE_PROFIT_ORDER` provider variant.
278    TakeProfitOrderTransaction(TakeProfitOrderTransaction),
279    /// `TAKE_PROFIT_ORDER_REJECT` provider variant.
280    TakeProfitOrderRejectTransaction(TakeProfitOrderRejectTransaction),
281    /// `STOP_LOSS_ORDER` provider variant.
282    StopLossOrderTransaction(StopLossOrderTransaction),
283    /// `STOP_LOSS_ORDER_REJECT` provider variant.
284    StopLossOrderRejectTransaction(StopLossOrderRejectTransaction),
285    /// `GUARANTEED_STOP_LOSS_ORDER` provider variant.
286    GuaranteedStopLossOrderTransaction(GuaranteedStopLossOrderTransaction),
287    /// `GUARANTEED_STOP_LOSS_ORDER_REJECT` provider variant.
288    GuaranteedStopLossOrderRejectTransaction(GuaranteedStopLossOrderRejectTransaction),
289    /// `TRAILING_STOP_LOSS_ORDER` provider variant.
290    TrailingStopLossOrderTransaction(TrailingStopLossOrderTransaction),
291    /// `TRAILING_STOP_LOSS_ORDER_REJECT` provider variant.
292    TrailingStopLossOrderRejectTransaction(TrailingStopLossOrderRejectTransaction),
293    /// `ORDER_FILL` provider variant.
294    OrderFillTransaction(OrderFillTransaction),
295    /// `ORDER_CANCEL` provider variant.
296    OrderCancelTransaction(OrderCancelTransaction),
297    /// `ORDER_CANCEL_REJECT` provider variant.
298    OrderCancelRejectTransaction(OrderCancelRejectTransaction),
299    /// `ORDER_CLIENT_EXTENSIONS_MODIFY` provider variant.
300    OrderClientExtensionsModifyTransaction(OrderClientExtensionsModifyTransaction),
301    /// `ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT` provider variant.
302    OrderClientExtensionsModifyRejectTransaction(OrderClientExtensionsModifyRejectTransaction),
303    /// `TRADE_CLIENT_EXTENSIONS_MODIFY` provider variant.
304    TradeClientExtensionsModifyTransaction(TradeClientExtensionsModifyTransaction),
305    /// `TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT` provider variant.
306    TradeClientExtensionsModifyRejectTransaction(TradeClientExtensionsModifyRejectTransaction),
307    /// `MARGIN_CALL_ENTER` provider variant.
308    MarginCallEnterTransaction(MarginCallEnterTransaction),
309    /// `MARGIN_CALL_EXTEND` provider variant.
310    MarginCallExtendTransaction(MarginCallExtendTransaction),
311    /// `MARGIN_CALL_EXIT` provider variant.
312    MarginCallExitTransaction(MarginCallExitTransaction),
313    /// `DELAYED_TRADE_CLOSURE` provider variant.
314    DelayedTradeClosureTransaction(DelayedTradeClosureTransaction),
315    /// `DAILY_FINANCING` provider variant.
316    DailyFinancingTransaction(DailyFinancingTransaction),
317    /// `DIVIDEND_ADJUSTMENT` provider variant.
318    DividendAdjustmentTransaction(DividendAdjustmentTransaction),
319    /// `RESET_RESETTABLE_PL` provider variant.
320    ResetResettablePLTransaction(ResetResettablePLTransaction),
321    /// Future provider variant with its bounded raw value.
322    Unknown {
323        /// Provider discriminator.
324        kind: String,
325        /// Bounded provider object.
326        raw: serde_json::Value,
327    },
328}
329
330impl<'de> Deserialize<'de> for Transaction {
331    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
332        let value = serde_json::Value::deserialize(deserializer)?;
333        let kind = value
334            .get("type")
335            .and_then(serde_json::Value::as_str)
336            .ok_or_else(|| serde::de::Error::custom("missing OANDA type discriminator"))?;
337        match kind {
338            "CREATE" => serde_json::from_value(value)
339                .map(Self::CreateTransaction)
340                .map_err(serde::de::Error::custom),
341            "CLOSE" => serde_json::from_value(value)
342                .map(Self::CloseTransaction)
343                .map_err(serde::de::Error::custom),
344            "REOPEN" => serde_json::from_value(value)
345                .map(Self::ReopenTransaction)
346                .map_err(serde::de::Error::custom),
347            "CLIENT_CONFIGURE" => serde_json::from_value(value)
348                .map(Self::ClientConfigureTransaction)
349                .map_err(serde::de::Error::custom),
350            "CLIENT_CONFIGURE_REJECT" => serde_json::from_value(value)
351                .map(Self::ClientConfigureRejectTransaction)
352                .map_err(serde::de::Error::custom),
353            "TRANSFER_FUNDS" => serde_json::from_value(value)
354                .map(Self::TransferFundsTransaction)
355                .map_err(serde::de::Error::custom),
356            "TRANSFER_FUNDS_REJECT" => serde_json::from_value(value)
357                .map(Self::TransferFundsRejectTransaction)
358                .map_err(serde::de::Error::custom),
359            "MARKET_ORDER" => serde_json::from_value(value)
360                .map(Self::MarketOrderTransaction)
361                .map_err(serde::de::Error::custom),
362            "MARKET_ORDER_REJECT" => serde_json::from_value(value)
363                .map(Self::MarketOrderRejectTransaction)
364                .map_err(serde::de::Error::custom),
365            "FIXED_PRICE_ORDER" => serde_json::from_value(value)
366                .map(Self::FixedPriceOrderTransaction)
367                .map_err(serde::de::Error::custom),
368            "LIMIT_ORDER" => serde_json::from_value(value)
369                .map(Self::LimitOrderTransaction)
370                .map_err(serde::de::Error::custom),
371            "LIMIT_ORDER_REJECT" => serde_json::from_value(value)
372                .map(Self::LimitOrderRejectTransaction)
373                .map_err(serde::de::Error::custom),
374            "STOP_ORDER" => serde_json::from_value(value)
375                .map(Self::StopOrderTransaction)
376                .map_err(serde::de::Error::custom),
377            "STOP_ORDER_REJECT" => serde_json::from_value(value)
378                .map(Self::StopOrderRejectTransaction)
379                .map_err(serde::de::Error::custom),
380            "MARKET_IF_TOUCHED_ORDER" => serde_json::from_value(value)
381                .map(Self::MarketIfTouchedOrderTransaction)
382                .map_err(serde::de::Error::custom),
383            "MARKET_IF_TOUCHED_ORDER_REJECT" => serde_json::from_value(value)
384                .map(Self::MarketIfTouchedOrderRejectTransaction)
385                .map_err(serde::de::Error::custom),
386            "TAKE_PROFIT_ORDER" => serde_json::from_value(value)
387                .map(Self::TakeProfitOrderTransaction)
388                .map_err(serde::de::Error::custom),
389            "TAKE_PROFIT_ORDER_REJECT" => serde_json::from_value(value)
390                .map(Self::TakeProfitOrderRejectTransaction)
391                .map_err(serde::de::Error::custom),
392            "STOP_LOSS_ORDER" => serde_json::from_value(value)
393                .map(Self::StopLossOrderTransaction)
394                .map_err(serde::de::Error::custom),
395            "STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
396                .map(Self::StopLossOrderRejectTransaction)
397                .map_err(serde::de::Error::custom),
398            "GUARANTEED_STOP_LOSS_ORDER" => serde_json::from_value(value)
399                .map(Self::GuaranteedStopLossOrderTransaction)
400                .map_err(serde::de::Error::custom),
401            "GUARANTEED_STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
402                .map(Self::GuaranteedStopLossOrderRejectTransaction)
403                .map_err(serde::de::Error::custom),
404            "TRAILING_STOP_LOSS_ORDER" => serde_json::from_value(value)
405                .map(Self::TrailingStopLossOrderTransaction)
406                .map_err(serde::de::Error::custom),
407            "TRAILING_STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
408                .map(Self::TrailingStopLossOrderRejectTransaction)
409                .map_err(serde::de::Error::custom),
410            "ORDER_FILL" => serde_json::from_value(value)
411                .map(Self::OrderFillTransaction)
412                .map_err(serde::de::Error::custom),
413            "ORDER_CANCEL" => serde_json::from_value(value)
414                .map(Self::OrderCancelTransaction)
415                .map_err(serde::de::Error::custom),
416            "ORDER_CANCEL_REJECT" => serde_json::from_value(value)
417                .map(Self::OrderCancelRejectTransaction)
418                .map_err(serde::de::Error::custom),
419            "ORDER_CLIENT_EXTENSIONS_MODIFY" => serde_json::from_value(value)
420                .map(Self::OrderClientExtensionsModifyTransaction)
421                .map_err(serde::de::Error::custom),
422            "ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT" => serde_json::from_value(value)
423                .map(Self::OrderClientExtensionsModifyRejectTransaction)
424                .map_err(serde::de::Error::custom),
425            "TRADE_CLIENT_EXTENSIONS_MODIFY" => serde_json::from_value(value)
426                .map(Self::TradeClientExtensionsModifyTransaction)
427                .map_err(serde::de::Error::custom),
428            "TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT" => serde_json::from_value(value)
429                .map(Self::TradeClientExtensionsModifyRejectTransaction)
430                .map_err(serde::de::Error::custom),
431            "MARGIN_CALL_ENTER" => serde_json::from_value(value)
432                .map(Self::MarginCallEnterTransaction)
433                .map_err(serde::de::Error::custom),
434            "MARGIN_CALL_EXTEND" => serde_json::from_value(value)
435                .map(Self::MarginCallExtendTransaction)
436                .map_err(serde::de::Error::custom),
437            "MARGIN_CALL_EXIT" => serde_json::from_value(value)
438                .map(Self::MarginCallExitTransaction)
439                .map_err(serde::de::Error::custom),
440            "DELAYED_TRADE_CLOSURE" => serde_json::from_value(value)
441                .map(Self::DelayedTradeClosureTransaction)
442                .map_err(serde::de::Error::custom),
443            "DAILY_FINANCING" => serde_json::from_value(value)
444                .map(Self::DailyFinancingTransaction)
445                .map_err(serde::de::Error::custom),
446            "DIVIDEND_ADJUSTMENT" => serde_json::from_value(value)
447                .map(Self::DividendAdjustmentTransaction)
448                .map_err(serde::de::Error::custom),
449            "RESET_RESETTABLE_PL" => serde_json::from_value(value)
450                .map(Self::ResetResettablePLTransaction)
451                .map_err(serde::de::Error::custom),
452            other => Ok(Self::Unknown {
453                kind: other.to_owned(),
454                raw: value,
455            }),
456        }
457    }
458}
459
460impl Serialize for Transaction {
461    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
462        let (kind, mut value) = match self {
463            Self::CreateTransaction(body) => (
464                "CREATE",
465                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
466            ),
467            Self::CloseTransaction(body) => (
468                "CLOSE",
469                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
470            ),
471            Self::ReopenTransaction(body) => (
472                "REOPEN",
473                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
474            ),
475            Self::ClientConfigureTransaction(body) => (
476                "CLIENT_CONFIGURE",
477                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
478            ),
479            Self::ClientConfigureRejectTransaction(body) => (
480                "CLIENT_CONFIGURE_REJECT",
481                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
482            ),
483            Self::TransferFundsTransaction(body) => (
484                "TRANSFER_FUNDS",
485                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
486            ),
487            Self::TransferFundsRejectTransaction(body) => (
488                "TRANSFER_FUNDS_REJECT",
489                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
490            ),
491            Self::MarketOrderTransaction(body) => (
492                "MARKET_ORDER",
493                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
494            ),
495            Self::MarketOrderRejectTransaction(body) => (
496                "MARKET_ORDER_REJECT",
497                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
498            ),
499            Self::FixedPriceOrderTransaction(body) => (
500                "FIXED_PRICE_ORDER",
501                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
502            ),
503            Self::LimitOrderTransaction(body) => (
504                "LIMIT_ORDER",
505                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
506            ),
507            Self::LimitOrderRejectTransaction(body) => (
508                "LIMIT_ORDER_REJECT",
509                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
510            ),
511            Self::StopOrderTransaction(body) => (
512                "STOP_ORDER",
513                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
514            ),
515            Self::StopOrderRejectTransaction(body) => (
516                "STOP_ORDER_REJECT",
517                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
518            ),
519            Self::MarketIfTouchedOrderTransaction(body) => (
520                "MARKET_IF_TOUCHED_ORDER",
521                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
522            ),
523            Self::MarketIfTouchedOrderRejectTransaction(body) => (
524                "MARKET_IF_TOUCHED_ORDER_REJECT",
525                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
526            ),
527            Self::TakeProfitOrderTransaction(body) => (
528                "TAKE_PROFIT_ORDER",
529                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
530            ),
531            Self::TakeProfitOrderRejectTransaction(body) => (
532                "TAKE_PROFIT_ORDER_REJECT",
533                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
534            ),
535            Self::StopLossOrderTransaction(body) => (
536                "STOP_LOSS_ORDER",
537                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
538            ),
539            Self::StopLossOrderRejectTransaction(body) => (
540                "STOP_LOSS_ORDER_REJECT",
541                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
542            ),
543            Self::GuaranteedStopLossOrderTransaction(body) => (
544                "GUARANTEED_STOP_LOSS_ORDER",
545                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
546            ),
547            Self::GuaranteedStopLossOrderRejectTransaction(body) => (
548                "GUARANTEED_STOP_LOSS_ORDER_REJECT",
549                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
550            ),
551            Self::TrailingStopLossOrderTransaction(body) => (
552                "TRAILING_STOP_LOSS_ORDER",
553                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
554            ),
555            Self::TrailingStopLossOrderRejectTransaction(body) => (
556                "TRAILING_STOP_LOSS_ORDER_REJECT",
557                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
558            ),
559            Self::OrderFillTransaction(body) => (
560                "ORDER_FILL",
561                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
562            ),
563            Self::OrderCancelTransaction(body) => (
564                "ORDER_CANCEL",
565                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
566            ),
567            Self::OrderCancelRejectTransaction(body) => (
568                "ORDER_CANCEL_REJECT",
569                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
570            ),
571            Self::OrderClientExtensionsModifyTransaction(body) => (
572                "ORDER_CLIENT_EXTENSIONS_MODIFY",
573                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
574            ),
575            Self::OrderClientExtensionsModifyRejectTransaction(body) => (
576                "ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT",
577                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
578            ),
579            Self::TradeClientExtensionsModifyTransaction(body) => (
580                "TRADE_CLIENT_EXTENSIONS_MODIFY",
581                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
582            ),
583            Self::TradeClientExtensionsModifyRejectTransaction(body) => (
584                "TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT",
585                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
586            ),
587            Self::MarginCallEnterTransaction(body) => (
588                "MARGIN_CALL_ENTER",
589                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
590            ),
591            Self::MarginCallExtendTransaction(body) => (
592                "MARGIN_CALL_EXTEND",
593                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
594            ),
595            Self::MarginCallExitTransaction(body) => (
596                "MARGIN_CALL_EXIT",
597                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
598            ),
599            Self::DelayedTradeClosureTransaction(body) => (
600                "DELAYED_TRADE_CLOSURE",
601                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
602            ),
603            Self::DailyFinancingTransaction(body) => (
604                "DAILY_FINANCING",
605                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
606            ),
607            Self::DividendAdjustmentTransaction(body) => (
608                "DIVIDEND_ADJUSTMENT",
609                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
610            ),
611            Self::ResetResettablePLTransaction(body) => (
612                "RESET_RESETTABLE_PL",
613                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
614            ),
615            Self::Unknown { kind, raw } => (kind.as_str(), raw.clone()),
616        };
617        let object = value
618            .as_object_mut()
619            .ok_or_else(|| serde::ser::Error::custom("OANDA variant must be an object"))?;
620        object.insert(
621            "type".to_owned(),
622            serde_json::Value::String(kind.to_owned()),
623        );
624        value.serialize(serializer)
625    }
626}