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]
240pub enum Transaction {
241    /// `CREATE` provider variant.
242    CreateTransaction(CreateTransaction),
243    /// `CLOSE` provider variant.
244    CloseTransaction(CloseTransaction),
245    /// `REOPEN` provider variant.
246    ReopenTransaction(ReopenTransaction),
247    /// `CLIENT_CONFIGURE` provider variant.
248    ClientConfigureTransaction(ClientConfigureTransaction),
249    /// `CLIENT_CONFIGURE_REJECT` provider variant.
250    ClientConfigureRejectTransaction(ClientConfigureRejectTransaction),
251    /// `TRANSFER_FUNDS` provider variant.
252    TransferFundsTransaction(TransferFundsTransaction),
253    /// `TRANSFER_FUNDS_REJECT` provider variant.
254    TransferFundsRejectTransaction(TransferFundsRejectTransaction),
255    /// `MARKET_ORDER` provider variant.
256    MarketOrderTransaction(MarketOrderTransaction),
257    /// `MARKET_ORDER_REJECT` provider variant.
258    MarketOrderRejectTransaction(MarketOrderRejectTransaction),
259    /// `FIXED_PRICE_ORDER` provider variant.
260    FixedPriceOrderTransaction(FixedPriceOrderTransaction),
261    /// `LIMIT_ORDER` provider variant.
262    LimitOrderTransaction(LimitOrderTransaction),
263    /// `LIMIT_ORDER_REJECT` provider variant.
264    LimitOrderRejectTransaction(LimitOrderRejectTransaction),
265    /// `STOP_ORDER` provider variant.
266    StopOrderTransaction(StopOrderTransaction),
267    /// `STOP_ORDER_REJECT` provider variant.
268    StopOrderRejectTransaction(StopOrderRejectTransaction),
269    /// `MARKET_IF_TOUCHED_ORDER` provider variant.
270    MarketIfTouchedOrderTransaction(MarketIfTouchedOrderTransaction),
271    /// `MARKET_IF_TOUCHED_ORDER_REJECT` provider variant.
272    MarketIfTouchedOrderRejectTransaction(MarketIfTouchedOrderRejectTransaction),
273    /// `TAKE_PROFIT_ORDER` provider variant.
274    TakeProfitOrderTransaction(TakeProfitOrderTransaction),
275    /// `TAKE_PROFIT_ORDER_REJECT` provider variant.
276    TakeProfitOrderRejectTransaction(TakeProfitOrderRejectTransaction),
277    /// `STOP_LOSS_ORDER` provider variant.
278    StopLossOrderTransaction(StopLossOrderTransaction),
279    /// `STOP_LOSS_ORDER_REJECT` provider variant.
280    StopLossOrderRejectTransaction(StopLossOrderRejectTransaction),
281    /// `GUARANTEED_STOP_LOSS_ORDER` provider variant.
282    GuaranteedStopLossOrderTransaction(GuaranteedStopLossOrderTransaction),
283    /// `GUARANTEED_STOP_LOSS_ORDER_REJECT` provider variant.
284    GuaranteedStopLossOrderRejectTransaction(GuaranteedStopLossOrderRejectTransaction),
285    /// `TRAILING_STOP_LOSS_ORDER` provider variant.
286    TrailingStopLossOrderTransaction(TrailingStopLossOrderTransaction),
287    /// `TRAILING_STOP_LOSS_ORDER_REJECT` provider variant.
288    TrailingStopLossOrderRejectTransaction(TrailingStopLossOrderRejectTransaction),
289    /// `ORDER_FILL` provider variant.
290    OrderFillTransaction(OrderFillTransaction),
291    /// `ORDER_CANCEL` provider variant.
292    OrderCancelTransaction(OrderCancelTransaction),
293    /// `ORDER_CANCEL_REJECT` provider variant.
294    OrderCancelRejectTransaction(OrderCancelRejectTransaction),
295    /// `ORDER_CLIENT_EXTENSIONS_MODIFY` provider variant.
296    OrderClientExtensionsModifyTransaction(OrderClientExtensionsModifyTransaction),
297    /// `ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT` provider variant.
298    OrderClientExtensionsModifyRejectTransaction(OrderClientExtensionsModifyRejectTransaction),
299    /// `TRADE_CLIENT_EXTENSIONS_MODIFY` provider variant.
300    TradeClientExtensionsModifyTransaction(TradeClientExtensionsModifyTransaction),
301    /// `TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT` provider variant.
302    TradeClientExtensionsModifyRejectTransaction(TradeClientExtensionsModifyRejectTransaction),
303    /// `MARGIN_CALL_ENTER` provider variant.
304    MarginCallEnterTransaction(MarginCallEnterTransaction),
305    /// `MARGIN_CALL_EXTEND` provider variant.
306    MarginCallExtendTransaction(MarginCallExtendTransaction),
307    /// `MARGIN_CALL_EXIT` provider variant.
308    MarginCallExitTransaction(MarginCallExitTransaction),
309    /// `DELAYED_TRADE_CLOSURE` provider variant.
310    DelayedTradeClosureTransaction(DelayedTradeClosureTransaction),
311    /// `DAILY_FINANCING` provider variant.
312    DailyFinancingTransaction(DailyFinancingTransaction),
313    /// `DIVIDEND_ADJUSTMENT` provider variant.
314    DividendAdjustmentTransaction(DividendAdjustmentTransaction),
315    /// `RESET_RESETTABLE_PL` provider variant.
316    ResetResettablePLTransaction(ResetResettablePLTransaction),
317    /// Future provider variant with its bounded raw value.
318    Unknown {
319        /// Provider discriminator.
320        kind: String,
321        /// Bounded provider object.
322        raw: serde_json::Value,
323    },
324}
325
326impl<'de> Deserialize<'de> for Transaction {
327    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
328        let value = serde_json::Value::deserialize(deserializer)?;
329        let kind = value
330            .get("type")
331            .and_then(serde_json::Value::as_str)
332            .ok_or_else(|| serde::de::Error::custom("missing OANDA type discriminator"))?;
333        match kind {
334            "CREATE" => serde_json::from_value(value)
335                .map(Self::CreateTransaction)
336                .map_err(serde::de::Error::custom),
337            "CLOSE" => serde_json::from_value(value)
338                .map(Self::CloseTransaction)
339                .map_err(serde::de::Error::custom),
340            "REOPEN" => serde_json::from_value(value)
341                .map(Self::ReopenTransaction)
342                .map_err(serde::de::Error::custom),
343            "CLIENT_CONFIGURE" => serde_json::from_value(value)
344                .map(Self::ClientConfigureTransaction)
345                .map_err(serde::de::Error::custom),
346            "CLIENT_CONFIGURE_REJECT" => serde_json::from_value(value)
347                .map(Self::ClientConfigureRejectTransaction)
348                .map_err(serde::de::Error::custom),
349            "TRANSFER_FUNDS" => serde_json::from_value(value)
350                .map(Self::TransferFundsTransaction)
351                .map_err(serde::de::Error::custom),
352            "TRANSFER_FUNDS_REJECT" => serde_json::from_value(value)
353                .map(Self::TransferFundsRejectTransaction)
354                .map_err(serde::de::Error::custom),
355            "MARKET_ORDER" => serde_json::from_value(value)
356                .map(Self::MarketOrderTransaction)
357                .map_err(serde::de::Error::custom),
358            "MARKET_ORDER_REJECT" => serde_json::from_value(value)
359                .map(Self::MarketOrderRejectTransaction)
360                .map_err(serde::de::Error::custom),
361            "FIXED_PRICE_ORDER" => serde_json::from_value(value)
362                .map(Self::FixedPriceOrderTransaction)
363                .map_err(serde::de::Error::custom),
364            "LIMIT_ORDER" => serde_json::from_value(value)
365                .map(Self::LimitOrderTransaction)
366                .map_err(serde::de::Error::custom),
367            "LIMIT_ORDER_REJECT" => serde_json::from_value(value)
368                .map(Self::LimitOrderRejectTransaction)
369                .map_err(serde::de::Error::custom),
370            "STOP_ORDER" => serde_json::from_value(value)
371                .map(Self::StopOrderTransaction)
372                .map_err(serde::de::Error::custom),
373            "STOP_ORDER_REJECT" => serde_json::from_value(value)
374                .map(Self::StopOrderRejectTransaction)
375                .map_err(serde::de::Error::custom),
376            "MARKET_IF_TOUCHED_ORDER" => serde_json::from_value(value)
377                .map(Self::MarketIfTouchedOrderTransaction)
378                .map_err(serde::de::Error::custom),
379            "MARKET_IF_TOUCHED_ORDER_REJECT" => serde_json::from_value(value)
380                .map(Self::MarketIfTouchedOrderRejectTransaction)
381                .map_err(serde::de::Error::custom),
382            "TAKE_PROFIT_ORDER" => serde_json::from_value(value)
383                .map(Self::TakeProfitOrderTransaction)
384                .map_err(serde::de::Error::custom),
385            "TAKE_PROFIT_ORDER_REJECT" => serde_json::from_value(value)
386                .map(Self::TakeProfitOrderRejectTransaction)
387                .map_err(serde::de::Error::custom),
388            "STOP_LOSS_ORDER" => serde_json::from_value(value)
389                .map(Self::StopLossOrderTransaction)
390                .map_err(serde::de::Error::custom),
391            "STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
392                .map(Self::StopLossOrderRejectTransaction)
393                .map_err(serde::de::Error::custom),
394            "GUARANTEED_STOP_LOSS_ORDER" => serde_json::from_value(value)
395                .map(Self::GuaranteedStopLossOrderTransaction)
396                .map_err(serde::de::Error::custom),
397            "GUARANTEED_STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
398                .map(Self::GuaranteedStopLossOrderRejectTransaction)
399                .map_err(serde::de::Error::custom),
400            "TRAILING_STOP_LOSS_ORDER" => serde_json::from_value(value)
401                .map(Self::TrailingStopLossOrderTransaction)
402                .map_err(serde::de::Error::custom),
403            "TRAILING_STOP_LOSS_ORDER_REJECT" => serde_json::from_value(value)
404                .map(Self::TrailingStopLossOrderRejectTransaction)
405                .map_err(serde::de::Error::custom),
406            "ORDER_FILL" => serde_json::from_value(value)
407                .map(Self::OrderFillTransaction)
408                .map_err(serde::de::Error::custom),
409            "ORDER_CANCEL" => serde_json::from_value(value)
410                .map(Self::OrderCancelTransaction)
411                .map_err(serde::de::Error::custom),
412            "ORDER_CANCEL_REJECT" => serde_json::from_value(value)
413                .map(Self::OrderCancelRejectTransaction)
414                .map_err(serde::de::Error::custom),
415            "ORDER_CLIENT_EXTENSIONS_MODIFY" => serde_json::from_value(value)
416                .map(Self::OrderClientExtensionsModifyTransaction)
417                .map_err(serde::de::Error::custom),
418            "ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT" => serde_json::from_value(value)
419                .map(Self::OrderClientExtensionsModifyRejectTransaction)
420                .map_err(serde::de::Error::custom),
421            "TRADE_CLIENT_EXTENSIONS_MODIFY" => serde_json::from_value(value)
422                .map(Self::TradeClientExtensionsModifyTransaction)
423                .map_err(serde::de::Error::custom),
424            "TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT" => serde_json::from_value(value)
425                .map(Self::TradeClientExtensionsModifyRejectTransaction)
426                .map_err(serde::de::Error::custom),
427            "MARGIN_CALL_ENTER" => serde_json::from_value(value)
428                .map(Self::MarginCallEnterTransaction)
429                .map_err(serde::de::Error::custom),
430            "MARGIN_CALL_EXTEND" => serde_json::from_value(value)
431                .map(Self::MarginCallExtendTransaction)
432                .map_err(serde::de::Error::custom),
433            "MARGIN_CALL_EXIT" => serde_json::from_value(value)
434                .map(Self::MarginCallExitTransaction)
435                .map_err(serde::de::Error::custom),
436            "DELAYED_TRADE_CLOSURE" => serde_json::from_value(value)
437                .map(Self::DelayedTradeClosureTransaction)
438                .map_err(serde::de::Error::custom),
439            "DAILY_FINANCING" => serde_json::from_value(value)
440                .map(Self::DailyFinancingTransaction)
441                .map_err(serde::de::Error::custom),
442            "DIVIDEND_ADJUSTMENT" => serde_json::from_value(value)
443                .map(Self::DividendAdjustmentTransaction)
444                .map_err(serde::de::Error::custom),
445            "RESET_RESETTABLE_PL" => serde_json::from_value(value)
446                .map(Self::ResetResettablePLTransaction)
447                .map_err(serde::de::Error::custom),
448            other => Ok(Self::Unknown {
449                kind: other.to_owned(),
450                raw: value,
451            }),
452        }
453    }
454}
455
456impl Serialize for Transaction {
457    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
458        let (kind, mut value) = match self {
459            Self::CreateTransaction(body) => (
460                "CREATE",
461                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
462            ),
463            Self::CloseTransaction(body) => (
464                "CLOSE",
465                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
466            ),
467            Self::ReopenTransaction(body) => (
468                "REOPEN",
469                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
470            ),
471            Self::ClientConfigureTransaction(body) => (
472                "CLIENT_CONFIGURE",
473                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
474            ),
475            Self::ClientConfigureRejectTransaction(body) => (
476                "CLIENT_CONFIGURE_REJECT",
477                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
478            ),
479            Self::TransferFundsTransaction(body) => (
480                "TRANSFER_FUNDS",
481                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
482            ),
483            Self::TransferFundsRejectTransaction(body) => (
484                "TRANSFER_FUNDS_REJECT",
485                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
486            ),
487            Self::MarketOrderTransaction(body) => (
488                "MARKET_ORDER",
489                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
490            ),
491            Self::MarketOrderRejectTransaction(body) => (
492                "MARKET_ORDER_REJECT",
493                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
494            ),
495            Self::FixedPriceOrderTransaction(body) => (
496                "FIXED_PRICE_ORDER",
497                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
498            ),
499            Self::LimitOrderTransaction(body) => (
500                "LIMIT_ORDER",
501                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
502            ),
503            Self::LimitOrderRejectTransaction(body) => (
504                "LIMIT_ORDER_REJECT",
505                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
506            ),
507            Self::StopOrderTransaction(body) => (
508                "STOP_ORDER",
509                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
510            ),
511            Self::StopOrderRejectTransaction(body) => (
512                "STOP_ORDER_REJECT",
513                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
514            ),
515            Self::MarketIfTouchedOrderTransaction(body) => (
516                "MARKET_IF_TOUCHED_ORDER",
517                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
518            ),
519            Self::MarketIfTouchedOrderRejectTransaction(body) => (
520                "MARKET_IF_TOUCHED_ORDER_REJECT",
521                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
522            ),
523            Self::TakeProfitOrderTransaction(body) => (
524                "TAKE_PROFIT_ORDER",
525                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
526            ),
527            Self::TakeProfitOrderRejectTransaction(body) => (
528                "TAKE_PROFIT_ORDER_REJECT",
529                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
530            ),
531            Self::StopLossOrderTransaction(body) => (
532                "STOP_LOSS_ORDER",
533                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
534            ),
535            Self::StopLossOrderRejectTransaction(body) => (
536                "STOP_LOSS_ORDER_REJECT",
537                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
538            ),
539            Self::GuaranteedStopLossOrderTransaction(body) => (
540                "GUARANTEED_STOP_LOSS_ORDER",
541                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
542            ),
543            Self::GuaranteedStopLossOrderRejectTransaction(body) => (
544                "GUARANTEED_STOP_LOSS_ORDER_REJECT",
545                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
546            ),
547            Self::TrailingStopLossOrderTransaction(body) => (
548                "TRAILING_STOP_LOSS_ORDER",
549                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
550            ),
551            Self::TrailingStopLossOrderRejectTransaction(body) => (
552                "TRAILING_STOP_LOSS_ORDER_REJECT",
553                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
554            ),
555            Self::OrderFillTransaction(body) => (
556                "ORDER_FILL",
557                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
558            ),
559            Self::OrderCancelTransaction(body) => (
560                "ORDER_CANCEL",
561                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
562            ),
563            Self::OrderCancelRejectTransaction(body) => (
564                "ORDER_CANCEL_REJECT",
565                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
566            ),
567            Self::OrderClientExtensionsModifyTransaction(body) => (
568                "ORDER_CLIENT_EXTENSIONS_MODIFY",
569                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
570            ),
571            Self::OrderClientExtensionsModifyRejectTransaction(body) => (
572                "ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT",
573                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
574            ),
575            Self::TradeClientExtensionsModifyTransaction(body) => (
576                "TRADE_CLIENT_EXTENSIONS_MODIFY",
577                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
578            ),
579            Self::TradeClientExtensionsModifyRejectTransaction(body) => (
580                "TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT",
581                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
582            ),
583            Self::MarginCallEnterTransaction(body) => (
584                "MARGIN_CALL_ENTER",
585                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
586            ),
587            Self::MarginCallExtendTransaction(body) => (
588                "MARGIN_CALL_EXTEND",
589                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
590            ),
591            Self::MarginCallExitTransaction(body) => (
592                "MARGIN_CALL_EXIT",
593                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
594            ),
595            Self::DelayedTradeClosureTransaction(body) => (
596                "DELAYED_TRADE_CLOSURE",
597                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
598            ),
599            Self::DailyFinancingTransaction(body) => (
600                "DAILY_FINANCING",
601                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
602            ),
603            Self::DividendAdjustmentTransaction(body) => (
604                "DIVIDEND_ADJUSTMENT",
605                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
606            ),
607            Self::ResetResettablePLTransaction(body) => (
608                "RESET_RESETTABLE_PL",
609                serde_json::to_value(body).map_err(serde::ser::Error::custom)?,
610            ),
611            Self::Unknown { kind, raw } => (kind.as_str(), raw.clone()),
612        };
613        let object = value
614            .as_object_mut()
615            .ok_or_else(|| serde::ser::Error::custom("OANDA variant must be an object"))?;
616        object.insert(
617            "type".to_owned(),
618            serde_json::Value::String(kind.to_owned()),
619        );
620        value.serialize(serializer)
621    }
622}