1use serde::{Deserialize, Serialize};
4
5use crate::{CapabilityRisk, McpExposure};
6
7pub const PLATFORM_SCHEMA_VERSION: u16 = 2;
8pub const PLATFORM_CONTRACT_VERSION: &str = "2.0";
9pub const PLATFORM_ACTION_GRAPH: &str = include_str!("../fixtures/v2/platform-action-graph.json");
10#[cfg(any(test, feature = "fixtures"))]
11#[doc(hidden)]
12pub const PLATFORM_SERVICE_STATUS_FIXTURE: &str =
13 include_str!("../fixtures/v2/platform-status.json");
14#[cfg(any(test, feature = "fixtures"))]
15#[doc(hidden)]
16pub const PLATFORM_CAPABILITIES_FIXTURE: &str =
17 include_str!("../fixtures/v2/platform-capabilities.json");
18#[cfg(any(test, feature = "fixtures"))]
19#[doc(hidden)]
20pub const PLATFORM_ASSETS_FIXTURE: &str = include_str!("../fixtures/v2/assets.json");
21#[cfg(any(test, feature = "fixtures"))]
22#[doc(hidden)]
23pub const PLATFORM_SWAP_QUOTE_FIXTURE: &str = include_str!("../fixtures/v2/swap-quote.json");
24#[cfg(any(test, feature = "fixtures"))]
25#[doc(hidden)]
26pub const PLATFORM_MARKETS_FIXTURE: &str = include_str!("../fixtures/v2/markets.json");
27#[cfg(any(test, feature = "fixtures"))]
28#[doc(hidden)]
29pub const PLATFORM_BOOK_FIXTURE: &str = include_str!("../fixtures/v2/book.json");
30#[cfg(any(test, feature = "fixtures"))]
31#[doc(hidden)]
32pub const PLATFORM_BBO_FIXTURE: &str = include_str!("../fixtures/v2/bbo.json");
33#[cfg(any(test, feature = "fixtures"))]
34#[doc(hidden)]
35pub const PLATFORM_FEES_FIXTURE: &str = include_str!("../fixtures/v2/fees.json");
36#[cfg(any(test, feature = "fixtures"))]
37#[doc(hidden)]
38pub const PLATFORM_STATUS_FIXTURE: &str = include_str!("../fixtures/v2/status.json");
39#[cfg(any(test, feature = "fixtures"))]
40#[doc(hidden)]
41pub const PLATFORM_CANDLES_FIXTURE: &str = include_str!("../fixtures/v2/candles.json");
42#[cfg(any(test, feature = "fixtures"))]
43#[doc(hidden)]
44pub const PLATFORM_MARK_FIXTURE: &str = include_str!("../fixtures/v2/mark.json");
45#[cfg(any(test, feature = "fixtures"))]
46#[doc(hidden)]
47pub const PLATFORM_EXECUTION_STATUS_FIXTURE: &str =
48 include_str!("../fixtures/v2/execution-status.json");
49#[cfg(any(test, feature = "fixtures"))]
50#[doc(hidden)]
51pub const PLATFORM_TWAPS_FIXTURE: &str = include_str!("../fixtures/v2/twaps.json");
52#[cfg(any(test, feature = "fixtures"))]
53#[doc(hidden)]
54pub const PLATFORM_TWAP_CHALLENGE_FIXTURE: &str =
55 include_str!("../fixtures/v2/twap-challenge.json");
56#[cfg(any(test, feature = "fixtures"))]
57#[doc(hidden)]
58pub const PLATFORM_TWAP_PREPARE_FIXTURE: &str = include_str!("../fixtures/v2/twap-prepare.json");
59#[cfg(any(test, feature = "fixtures"))]
60#[doc(hidden)]
61pub const PLATFORM_TWAP_SUBMIT_FIXTURE: &str = include_str!("../fixtures/v2/twap-submit.json");
62#[cfg(any(test, feature = "fixtures"))]
63#[doc(hidden)]
64pub const PLATFORM_PORTFOLIO_HISTORY_FIXTURE: &str =
65 include_str!("../fixtures/v2/portfolio-history.json");
66#[cfg(any(test, feature = "fixtures"))]
67#[doc(hidden)]
68pub const PLATFORM_PORTFOLIO_FIXTURE: &str = include_str!("../fixtures/v2/portfolio.json");
69#[cfg(any(test, feature = "fixtures"))]
70#[doc(hidden)]
71pub const PLATFORM_REWARDS_FIXTURE: &str = include_str!("../fixtures/v2/rewards.json");
72#[cfg(any(test, feature = "fixtures"))]
73#[doc(hidden)]
74pub const PLATFORM_REFERRALS_FIXTURE: &str = include_str!("../fixtures/v2/referrals.json");
75#[cfg(any(test, feature = "fixtures"))]
76#[doc(hidden)]
77pub const PLATFORM_REFERRAL_LINK_FIXTURE: &str = include_str!("../fixtures/v2/referral-link.json");
78#[cfg(any(test, feature = "fixtures"))]
79#[doc(hidden)]
80pub const PLATFORM_REFERRAL_CLAIM_FIXTURE: &str =
81 include_str!("../fixtures/v2/referral-claim.json");
82#[cfg(any(test, feature = "fixtures"))]
83#[doc(hidden)]
84pub const PLATFORM_VAULT_STATUS_FIXTURE: &str = include_str!("../fixtures/v2/vault-status.json");
85#[cfg(any(test, feature = "fixtures"))]
86#[doc(hidden)]
87pub const PLATFORM_VAULT_PAUSE_PREPARE_FIXTURE: &str =
88 include_str!("../fixtures/v2/vault-pause-prepare.json");
89#[cfg(any(test, feature = "fixtures"))]
90#[doc(hidden)]
91pub const PLATFORM_VAULT_SETUP_PREPARE_FIXTURE: &str =
92 include_str!("../fixtures/v2/vault-setup-prepare.json");
93pub const PLATFORM_VAULT_DELEGATE_PREPARE_FIXTURE: &str =
94 include_str!("../fixtures/v2/vault-delegate-prepare.json");
95pub const PLATFORM_VAULT_POLICY_PREPARE_FIXTURE: &str =
96 include_str!("../fixtures/v2/vault-policy-prepare.json");
97pub const PLATFORM_VAULT_DEPOSIT_PREPARE_FIXTURE: &str =
98 include_str!("../fixtures/v2/vault-deposit-prepare.json");
99pub const PLATFORM_VAULT_WITHDRAW_PREPARE_FIXTURE: &str =
100 include_str!("../fixtures/v2/vault-withdraw-prepare.json");
101pub const PLATFORM_VAULT_SUBMIT_FIXTURE: &str = include_str!("../fixtures/v2/vault-submit.json");
102#[cfg(any(test, feature = "fixtures"))]
103#[doc(hidden)]
104pub const PLATFORM_BUGS_FIXTURE: &str = include_str!("../fixtures/v2/bugs.json");
105#[cfg(any(test, feature = "fixtures"))]
106#[doc(hidden)]
107pub const PLATFORM_BUG_SUBMIT_FIXTURE: &str = include_str!("../fixtures/v2/bug-submit.json");
108#[cfg(any(test, feature = "fixtures"))]
109#[doc(hidden)]
110pub const PLATFORM_TRADES_FIXTURE: &str = include_str!("../fixtures/v2/trades.json");
111#[cfg(any(test, feature = "fixtures"))]
112#[doc(hidden)]
113pub const PLATFORM_ACCOUNT_FIXTURE: &str = include_str!("../fixtures/v2/account.json");
114#[cfg(any(test, feature = "fixtures"))]
115#[doc(hidden)]
116pub const PLATFORM_MAKER_REPUTATION_FIXTURE: &str =
117 include_str!("../fixtures/v2/maker-reputation.json");
118#[cfg(any(test, feature = "fixtures"))]
119#[doc(hidden)]
120pub const PLATFORM_MAKER_STATUS_FIXTURE: &str = include_str!("../fixtures/v2/maker-status.json");
121#[cfg(any(test, feature = "fixtures"))]
122#[doc(hidden)]
123pub const PLATFORM_MAKER_STREAM_FIXTURE: &str = include_str!("../fixtures/v2/maker-stream.json");
124#[cfg(any(test, feature = "fixtures"))]
125#[doc(hidden)]
126pub const PLATFORM_TWAP_STREAM_FIXTURE: &str = include_str!("../fixtures/v2/twap-stream.json");
127#[cfg(any(test, feature = "fixtures"))]
128#[doc(hidden)]
129pub const PLATFORM_EXECUTION_STREAM_FIXTURE: &str =
130 include_str!("../fixtures/v2/execution-stream.json");
131#[cfg(any(test, feature = "fixtures"))]
132#[doc(hidden)]
133pub const PLATFORM_ORDER_CHALLENGE_FIXTURE: &str =
134 include_str!("../fixtures/v2/order-challenge.json");
135#[cfg(any(test, feature = "fixtures"))]
136#[doc(hidden)]
137pub const PLATFORM_ORDER_PREPARE_FIXTURE: &str = include_str!("../fixtures/v2/order-prepare.json");
138#[cfg(any(test, feature = "fixtures"))]
139#[doc(hidden)]
140pub const PLATFORM_ORDER_SUBMIT_FIXTURE: &str = include_str!("../fixtures/v2/order-submit.json");
141#[cfg(any(test, feature = "fixtures"))]
142#[doc(hidden)]
143pub const PLATFORM_ORDER_STATUS_FIXTURE: &str = include_str!("../fixtures/v2/order-status.json");
144
145#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
146#[serde(rename_all = "snake_case")]
147pub enum PermissionSource {
148 ExternalAgentOwner,
149}
150
151#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
152#[serde(rename_all = "snake_case")]
153pub enum SigningLocation {
154 External,
155}
156
157#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
158#[serde(deny_unknown_fields)]
159pub struct PlatformAuthority {
160 pub permission_source: PermissionSource,
161 pub signing_location: SigningLocation,
162 pub accepts_private_keys: bool,
163}
164
165#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
166#[serde(rename_all = "snake_case")]
167pub enum PlatformTransport {
168 Http,
169 Websocket,
170 Mcp,
171}
172
173#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
174#[serde(rename_all = "snake_case")]
175pub enum PlatformMarketState {
176 Active,
177 ReadOnly,
178 QuoteOnly,
179 CancelOnly,
180 Paused,
181 Warming,
182 Degraded,
183 Unavailable,
184}
185
186#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
187#[serde(rename_all = "snake_case")]
188pub enum PlatformOrderState {
189 Created,
190 Accepted,
191 Open,
192 PartiallyFilled,
193 Filled,
194 CancelPending,
195 Cancelled,
196 Expired,
197 Rejected,
198}
199
200#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
201#[serde(rename_all = "snake_case")]
202pub enum PlatformSettlementState {
203 NotApplicable,
204 Pending,
205 Confirmed,
206 Failed,
207}
208
209#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
210#[serde(rename_all = "snake_case")]
211pub enum PlatformPublicErrorCode {
212 InvalidRequest,
213 UnsupportedCapability,
214 MarketUnavailable,
215 MarketWarming,
216 QuoteUnavailable,
217 QuoteExpired,
218 PriceBoundFailed,
219 InsufficientBalance,
220 PolicyRejected,
221 SessionExpired,
222 SequenceConflict,
223 DuplicateClientId,
224 OrderRejected,
225 OrderNotFound,
226 CancelTooLate,
227 SelfTradePrevented,
228 DeadManExpired,
229 RateLimited,
230 TemporarilyUnavailable,
231 SubmissionAmbiguous,
232 SettlementPending,
233 SettlementFailed,
234}
235
236#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
238#[serde(deny_unknown_fields)]
239pub struct ExactAmount {
240 pub asset_id: String,
241 pub atoms: String,
242}
243
244#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
246#[serde(deny_unknown_fields)]
247pub struct SequenceEnvelope {
248 pub stream_id: String,
249 pub sequence: String,
250 pub previous_sequence: Option<String>,
251 pub server_time_ms: u64,
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub snapshot_id: Option<String>,
254}
255
256#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
257#[serde(deny_unknown_fields)]
258pub struct PageRequest {
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub cursor: Option<String>,
261 #[serde(skip_serializing_if = "Option::is_none")]
262 pub limit: Option<u32>,
263}
264
265#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
266#[serde(deny_unknown_fields)]
267pub struct PageInfo {
268 pub next_cursor: Option<String>,
269 pub has_more: bool,
270}
271
272#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
273#[serde(deny_unknown_fields)]
274pub struct PublicOperationError {
275 pub code: PlatformPublicErrorCode,
276 pub message: String,
277 pub retryable: bool,
278 #[serde(skip_serializing_if = "Option::is_none")]
279 pub retry_after_ms: Option<u64>,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 pub operation_id: Option<String>,
282}
283
284#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
286#[serde(deny_unknown_fields)]
287pub struct LivePlatformCapability {
288 pub id: String,
289 pub risk: CapabilityRisk,
290 pub required_scope: String,
291 pub transports: Vec<PlatformTransport>,
292 pub mcp_exposure: McpExposure,
293}
294
295#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
297#[serde(deny_unknown_fields)]
298pub struct PlatformDiscoveryResponse {
299 pub schema_version: u16,
300 pub contract_version: String,
301 pub server_time_ms: u64,
302 pub authority: PlatformAuthority,
303 pub capabilities: Vec<LivePlatformCapability>,
304}
305
306#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
307#[serde(rename_all = "snake_case")]
308pub enum PlatformServiceState {
309 Operational,
310 Degraded,
311}
312
313#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
315#[serde(deny_unknown_fields)]
316pub struct PlatformServiceStatusResponse {
317 pub schema_version: u16,
318 pub contract_version: String,
319 pub server_time_ms: u64,
320 pub status: PlatformServiceState,
321 pub available_operations: u32,
322}
323
324#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
325#[serde(rename_all = "snake_case")]
326pub enum PlatformActionKind {
327 Discovery,
328 Read,
329 Prepare,
330 ExternalSignature,
331 Submit,
332 Receipt,
333 Stream,
334}
335
336#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
337#[serde(deny_unknown_fields)]
338pub struct PlatformGraphRelation {
339 pub from: String,
340 pub to: String,
341 pub kind: String,
342}
343
344#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
345#[serde(deny_unknown_fields)]
346pub struct PlatformGraphModule {
347 pub id: String,
348 pub client_property: String,
349 pub capability_ids: Vec<String>,
350}
351
352#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
353#[serde(deny_unknown_fields)]
354pub struct PlatformOperationTransport {
355 pub transport: PlatformTransport,
356 #[serde(skip_serializing_if = "Option::is_none")]
357 pub method: Option<String>,
358 #[serde(skip_serializing_if = "Option::is_none")]
359 pub path: Option<String>,
360 #[serde(skip_serializing_if = "Option::is_none")]
361 pub tool: Option<String>,
362}
363
364#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
365#[serde(deny_unknown_fields)]
366pub struct PlatformOperation {
367 pub id: String,
368 pub capability_id: String,
369 pub kind: PlatformActionKind,
370 pub summary: String,
371 pub transports: Vec<PlatformOperationTransport>,
372 pub available: bool,
373}
374
375#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
376#[serde(deny_unknown_fields)]
377pub struct PlatformWorkflowNode {
378 pub id: String,
379 pub kind: PlatformActionKind,
380 pub capability_id: Option<String>,
381 pub operation_ids: Vec<String>,
382 pub available: bool,
383}
384
385#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
386#[serde(deny_unknown_fields)]
387pub struct PlatformWorkflowEdge {
388 pub from: String,
389 pub to: String,
390 pub condition: String,
391}
392
393#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
394#[serde(deny_unknown_fields)]
395pub struct PlatformWorkflow {
396 pub id: String,
397 pub entry_node: String,
398 pub nodes: Vec<PlatformWorkflowNode>,
399 pub edges: Vec<PlatformWorkflowEdge>,
400}
401
402#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
405#[serde(deny_unknown_fields)]
406pub struct PlatformActionGraphResponse {
407 pub schema_version: u16,
408 pub contract_version: String,
409 pub graph_version: String,
410 pub entry_operation_id: String,
411 pub authority: PlatformAuthority,
412 pub entities: Vec<String>,
413 pub relations: Vec<PlatformGraphRelation>,
414 pub modules: Vec<PlatformGraphModule>,
415 pub operations: Vec<PlatformOperation>,
416 pub workflows: Vec<PlatformWorkflow>,
417}
418
419impl PlatformActionGraphResponse {
420 pub fn foundation() -> Self {
421 serde_json::from_str(PLATFORM_ACTION_GRAPH)
422 .expect("embedded platform action graph must be valid")
423 }
424
425 pub fn project_availability(
428 &mut self,
429 live_capability_ids: &std::collections::BTreeSet<String>,
430 ) {
431 for operation in &mut self.operations {
432 operation.available = live_capability_ids.contains(&operation.capability_id);
433 }
434 for workflow in &mut self.workflows {
435 for node in &mut workflow.nodes {
436 node.available = node
437 .capability_id
438 .as_ref()
439 .is_none_or(|capability_id| live_capability_ids.contains(capability_id));
440 }
441 }
442 }
443}
444
445#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
446#[serde(rename_all = "snake_case")]
447pub enum PlatformNetwork {
448 Solana,
449}
450
451#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
453#[serde(deny_unknown_fields)]
454pub struct PlatformAsset {
455 pub asset_id: String,
456 pub symbol: String,
457 pub name: String,
458 pub decimals: u8,
459 #[serde(skip_serializing_if = "Option::is_none")]
460 pub logo_url: Option<String>,
461 pub network: PlatformNetwork,
462}
463
464#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
465#[serde(deny_unknown_fields)]
466pub struct PlatformAssetsResponse {
467 pub schema_version: u16,
468 pub contract_version: String,
469 pub server_time_ms: u64,
470 pub assets: Vec<PlatformAsset>,
471 pub page: PageInfo,
472}
473
474#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
478#[serde(deny_unknown_fields)]
479pub struct PlatformSwapQuoteRequest {
480 pub input_asset_id: String,
481 pub output_asset_id: String,
482 pub amount_in_atoms: String,
483 #[serde(default)]
484 pub maximum_tolerance_bps: u16,
485}
486
487#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
489#[serde(deny_unknown_fields)]
490pub struct PlatformSwapQuoteResponse {
491 pub schema_version: u16,
492 pub contract_version: String,
493 pub quote_id: String,
494 pub server_time_ms: u64,
495 pub expires_at_ms: u64,
496 pub input_asset_id: String,
497 pub output_asset_id: String,
498 pub amount_in_atoms: String,
499 pub amount_in_consumed_atoms: String,
500 pub amount_out_atoms: String,
501 pub minimum_output_atoms: String,
502 pub input_fee_atoms: String,
503 pub output_fee_atoms: String,
504 pub maximum_tolerance_bps: u16,
505 pub reference_price: String,
506 pub price_impact_pct: String,
507 pub provider: String,
508}
509
510#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
511#[serde(rename_all = "snake_case")]
512pub enum PlatformMarketAction {
513 Quote,
514 ExecuteImmediate,
515 PlaceOrder,
516 ScheduleTwap,
517}
518
519#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
521#[serde(deny_unknown_fields)]
522pub struct PlatformMarket {
523 pub market_id: String,
524 pub label: String,
525 pub base_asset_id: String,
526 pub quote_asset_id: String,
527 pub status: PlatformMarketState,
528 pub available_actions: Vec<PlatformMarketAction>,
529}
530
531#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
532#[serde(deny_unknown_fields)]
533pub struct PlatformMarketsResponse {
534 pub schema_version: u16,
535 pub contract_version: String,
536 pub server_time_ms: u64,
537 pub markets: Vec<PlatformMarket>,
538 pub page: PageInfo,
539}
540
541#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
542#[serde(deny_unknown_fields)]
543pub struct PlatformBookLevel {
544 pub price_atoms: String,
546 pub size_atoms: String,
548}
549
550#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
551#[serde(rename_all = "snake_case")]
552pub enum PlatformBookSide {
553 Bid,
554 Ask,
555}
556
557#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
558#[serde(deny_unknown_fields)]
559pub struct PlatformBookChange {
560 pub side: PlatformBookSide,
561 pub price_atoms: String,
562 pub size_atoms: String,
564}
565
566#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
567#[serde(deny_unknown_fields)]
568pub struct PlatformBookSnapshotResponse {
569 pub schema_version: u16,
570 pub contract_version: String,
571 pub market_id: String,
572 pub stream_id: String,
573 pub sequence: String,
574 pub server_time_ms: u64,
575 pub snapshot_id: String,
576 pub bids: Vec<PlatformBookLevel>,
577 pub asks: Vec<PlatformBookLevel>,
578}
579
580#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
581#[serde(deny_unknown_fields)]
582pub struct PlatformBestBidAskResponse {
583 pub schema_version: u16,
584 pub contract_version: String,
585 pub market_id: String,
586 pub stream_id: String,
587 pub sequence: String,
588 pub server_time_ms: u64,
589 pub best_bid: Option<PlatformBookLevel>,
590 pub best_ask: Option<PlatformBookLevel>,
591}
592
593#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
594#[serde(deny_unknown_fields)]
595pub struct PlatformFeeScheduleResponse {
596 pub schema_version: u16,
597 pub contract_version: String,
598 pub market_id: String,
599 pub server_time_ms: u64,
600 pub passive_maker_fee_bps: u16,
601 pub maximum_immediate_execution_fee_bps: u16,
602 pub book_prices_include_trading_fees: bool,
603 pub exact_fee_returned_by_quote: bool,
604}
605
606#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
607#[serde(deny_unknown_fields)]
608pub struct PlatformMarketStatusResponse {
609 pub schema_version: u16,
610 pub contract_version: String,
611 pub market_id: String,
612 pub server_time_ms: u64,
613 pub status: PlatformMarketState,
614 pub tick_size_atoms: String,
615 pub minimum_order_size_atoms: String,
616}
617
618#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
620#[serde(deny_unknown_fields)]
621pub struct PlatformCandle {
622 pub started_at_ms: u64,
623 pub open_price: String,
624 pub high_price: String,
625 pub low_price: String,
626 pub close_price: String,
627}
628
629#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
630#[serde(deny_unknown_fields)]
631pub struct PlatformCandlesResponse {
632 pub schema_version: u16,
633 pub contract_version: String,
634 pub market_id: String,
635 pub server_time_ms: u64,
636 pub resolution_seconds: u32,
637 pub candles: Vec<PlatformCandle>,
638}
639
640#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
641#[serde(deny_unknown_fields)]
642pub struct PlatformMarkResponse {
643 pub schema_version: u16,
644 pub contract_version: String,
645 pub market_id: String,
646 pub server_time_ms: u64,
647 pub price_atoms_per_base_unit: Option<String>,
648 pub quote_decimals: u8,
649 pub stale: bool,
650 pub age_ms: Option<u64>,
651}
652
653#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
654#[serde(rename_all = "snake_case")]
655pub enum PlatformExecutionState {
656 Prepared,
657 Confirmed,
658}
659
660#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
663#[serde(deny_unknown_fields)]
664pub struct PlatformExecutionStatusResponse {
665 pub schema_version: u16,
666 pub contract_version: String,
667 pub execution_id: String,
668 pub market_id: String,
669 pub status: PlatformExecutionState,
670 pub signature: Option<String>,
671 pub settlement: PlatformSettlementState,
672 pub updated_at_ms: u64,
673}
674
675#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
678#[serde(deny_unknown_fields)]
679pub struct PlatformExecutionRow {
680 pub execution_id: String,
681 pub market_id: String,
682 pub status: PlatformExecutionState,
683 pub signature: Option<String>,
684 pub settlement: PlatformSettlementState,
685 pub updated_at_ms: u64,
686}
687
688#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
691#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
692pub enum PlatformExecutionCommand {
693 Watch { execution_ids: Vec<String> },
694}
695
696#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
704#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
705pub enum PlatformExecutionEvent {
706 ExecutionsSnapshot {
707 schema_version: u16,
708 contract_version: String,
709 market_id: String,
710 stream_id: String,
711 sequence: String,
712 server_time_ms: u64,
713 executions: Vec<PlatformExecutionRow>,
714 unknown_execution_ids: Vec<String>,
715 },
716 ExecutionUpdate {
717 schema_version: u16,
718 contract_version: String,
719 market_id: String,
720 stream_id: String,
721 sequence: String,
722 previous_sequence: String,
723 server_time_ms: u64,
724 execution: PlatformExecutionRow,
725 },
726 ExecutionExpired {
727 schema_version: u16,
728 contract_version: String,
729 market_id: String,
730 stream_id: String,
731 sequence: String,
732 previous_sequence: String,
733 server_time_ms: u64,
734 execution_id: String,
735 },
736 ExecutionUnknown {
737 schema_version: u16,
738 contract_version: String,
739 market_id: String,
740 stream_id: String,
741 sequence: String,
742 previous_sequence: String,
743 server_time_ms: u64,
744 execution_id: String,
745 },
746 Heartbeat {
747 schema_version: u16,
748 contract_version: String,
749 market_id: String,
750 stream_id: String,
751 sequence: String,
752 previous_sequence: String,
753 server_time_ms: u64,
754 },
755}
756
757#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
758#[serde(rename_all = "snake_case")]
759pub enum PlatformTwapState {
760 Active,
761 Completed,
762 Cancelled,
763}
764
765#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
766#[serde(deny_unknown_fields)]
767pub struct PlatformTwapFill {
768 pub fill_id: String,
769 pub size_atoms: String,
770 pub price_atoms: String,
771 pub gross_quote_atoms: String,
772 pub base_fee_atoms: String,
773 pub quote_fee_atoms: String,
774 pub signature: Option<String>,
775 pub observed_at_ms: u64,
776}
777
778#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
779#[serde(deny_unknown_fields)]
780pub struct PlatformTwap {
781 pub twap_id: String,
782 pub side: PlatformTradeSide,
783 pub status: PlatformTwapState,
784 pub slices_total: u16,
785 pub slices_executed: u16,
786 pub interval_slots: u32,
787 pub maximum_tolerance_bps: u16,
788 pub limit_price_atoms: String,
789 pub total_size_atoms: String,
790 pub executed_size_atoms: String,
791 pub gross_quote_executed_atoms: String,
792 pub complete_execution_value: bool,
793 pub created_at_ms: u64,
794 pub completed_at_ms: Option<u64>,
795 pub placed_signature: Option<String>,
796 pub terminal_signature: Option<String>,
797 pub fills: Vec<PlatformTwapFill>,
798}
799
800#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
801#[serde(deny_unknown_fields)]
802pub struct PlatformTwapsResponse {
803 pub schema_version: u16,
804 pub contract_version: String,
805 pub market_id: String,
806 pub wallet_address: String,
807 pub server_time_ms: u64,
808 pub twaps: Vec<PlatformTwap>,
809}
810
811#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
812#[serde(rename_all = "snake_case")]
813pub enum PlatformTwapControlAction {
814 Place,
815 Cancel,
816}
817
818#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
821#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
822pub enum PlatformTwapChallengeRequest {
823 Place {
824 owner_wallet: String,
825 session_public_key: String,
826 side: PlatformTradeSide,
827 total_size_atoms: String,
828 slices_total: u16,
829 maximum_tolerance_bps: u16,
830 interval_slots: u32,
834 limit_price_atoms: String,
835 },
836 Cancel {
837 owner_wallet: String,
838 session_public_key: String,
839 twap_id: String,
840 },
841}
842
843#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
844#[serde(deny_unknown_fields)]
845pub struct PlatformTwapChallengeResponse {
846 pub schema_version: u16,
847 pub contract_version: String,
848 pub challenge_id: String,
849 pub market_id: String,
850 pub action: PlatformTwapControlAction,
851 pub twap_id: String,
852 pub authorization_payload_base64: String,
853 pub server_time_ms: u64,
854 pub expires_at_ms: u64,
855}
856
857#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
859#[serde(deny_unknown_fields)]
860pub struct PlatformTwapPrepareAuthorization {
861 pub challenge_id: String,
862 pub authorization_signature: String,
864}
865
866#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
870#[serde(untagged)]
871pub enum PlatformTwapPrepareRequest {
872 Authorized(PlatformTwapPrepareAuthorization),
873 Direct(PlatformTwapChallengeRequest),
874}
875
876#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
877#[serde(deny_unknown_fields)]
878pub struct PlatformTwapPrepareResponse {
879 pub schema_version: u16,
880 pub contract_version: String,
881 pub twap_control_id: String,
882 pub market_id: String,
883 pub action: PlatformTwapControlAction,
884 pub twap_id: String,
885 pub transaction_base64: String,
888 pub recent_blockhash: String,
889 pub last_valid_block_height: u64,
890 pub expires_at_ms: u64,
891}
892
893#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
894#[serde(deny_unknown_fields)]
895pub struct PlatformTwapSubmitRequest {
896 pub twap_control_id: String,
897 pub signed_transaction_base64: String,
898 pub idempotency_key: String,
899}
900
901#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
902#[serde(deny_unknown_fields)]
903pub struct PlatformTwapSubmitResponse {
904 pub schema_version: u16,
905 pub contract_version: String,
906 pub twap_control_id: String,
907 pub market_id: String,
908 pub action: PlatformTwapControlAction,
909 pub twap_id: String,
910 pub signature: String,
911 pub status: PlatformOrderSubmissionStatus,
912}
913
914#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
921#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
922#[allow(clippy::large_enum_variant)]
923pub enum PlatformTwapEvent {
924 TwapsSnapshot {
925 schema_version: u16,
926 contract_version: String,
927 market_id: String,
928 wallet_address: String,
929 stream_id: String,
930 sequence: String,
931 server_time_ms: u64,
932 twaps: Vec<PlatformTwap>,
933 },
934 TwapUpdate {
935 schema_version: u16,
936 contract_version: String,
937 market_id: String,
938 wallet_address: String,
939 stream_id: String,
940 sequence: String,
941 previous_sequence: String,
942 server_time_ms: u64,
943 twap: PlatformTwap,
944 },
945 Heartbeat {
946 schema_version: u16,
947 contract_version: String,
948 market_id: String,
949 wallet_address: String,
950 stream_id: String,
951 sequence: String,
952 previous_sequence: String,
953 server_time_ms: u64,
954 },
955}
956
957#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
958pub enum PlatformPortfolioHistoryRange {
959 #[serde(rename = "24h")]
960 Day,
961 #[serde(rename = "7d")]
962 Week,
963 #[serde(rename = "30d")]
964 Month,
965}
966
967#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
968#[serde(deny_unknown_fields)]
969pub struct PlatformPortfolioHistoryPoint {
970 pub recorded_at_ms: u64,
971 pub equity_usd_micros: String,
972 pub available_usd_micros: String,
973 pub locked_usd_micros: String,
974 pub market_count: u32,
975}
976
977#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
980#[serde(deny_unknown_fields)]
981pub struct PlatformPortfolioHistoryResponse {
982 pub schema_version: u16,
983 pub contract_version: String,
984 pub wallet_address: String,
985 pub server_time_ms: u64,
986 pub range: PlatformPortfolioHistoryRange,
987 pub points: Vec<PlatformPortfolioHistoryPoint>,
988 pub collecting: bool,
989 pub first_sample_ms: Option<u64>,
990 pub last_sample_ms: Option<u64>,
991}
992
993#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
998#[serde(deny_unknown_fields)]
999pub struct PlatformPortfolioBalance {
1000 pub asset_id: String,
1001 pub available_atoms: String,
1003 pub locked_atoms: String,
1005 pub total_atoms: String,
1007 pub value_usd_micros: Option<String>,
1009}
1010
1011#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1014#[serde(deny_unknown_fields)]
1015pub struct PlatformPortfolioPosition {
1016 pub market_id: String,
1017 pub base_asset_id: String,
1018 pub quote_asset_id: String,
1019 pub base_available_atoms: String,
1020 pub base_locked_atoms: String,
1021 pub quote_available_atoms: String,
1022 pub quote_locked_atoms: String,
1023}
1024
1025#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1027#[serde(deny_unknown_fields)]
1028pub struct PlatformPortfolioOrder {
1029 pub market_id: String,
1030 pub order_id: String,
1031 pub side: PlatformTradeSide,
1032 pub order_type: PlatformOrderType,
1033 pub state: PlatformOrderState,
1034 pub limit_price_atoms: String,
1035 pub original_size_atoms: String,
1036 pub remaining_size_atoms: String,
1037}
1038
1039#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1041#[serde(deny_unknown_fields)]
1042pub struct PlatformPortfolioFill {
1043 pub market_id: String,
1044 pub fill_id: String,
1045 pub side: PlatformTradeSide,
1046 pub price_atoms: String,
1047 pub size_atoms: String,
1048 pub fee_quote_atoms: String,
1049 pub fee_is_final: bool,
1050 pub settlement: PlatformSettlementState,
1051 pub executed_at_ms: u64,
1052 pub confirmed_at_ms: Option<u64>,
1053 pub transaction_id: Option<String>,
1054 pub realized_pnl_quote_atoms: String,
1055}
1056
1057#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1064#[serde(deny_unknown_fields)]
1065pub struct PlatformPortfolioResponse {
1066 pub schema_version: u16,
1067 pub contract_version: String,
1068 pub wallet_address: String,
1069 pub server_time_ms: u64,
1070 pub observed_at_ms: u64,
1072 pub observed_slot: String,
1074 pub market_count: u32,
1076 pub balances: Vec<PlatformPortfolioBalance>,
1077 pub positions: Vec<PlatformPortfolioPosition>,
1078 pub open_orders: Vec<PlatformPortfolioOrder>,
1080 pub recent_fills: Vec<PlatformPortfolioFill>,
1082 pub unavailable_market_ids: Vec<String>,
1085 pub equity_usd_micros: Option<String>,
1087 pub available_usd_micros: Option<String>,
1089 pub locked_usd_micros: Option<String>,
1091 pub valuation_complete: bool,
1092 pub unpriced_asset_ids: Vec<String>,
1093}
1094
1095#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1096#[serde(rename_all = "snake_case")]
1097pub enum PlatformVaultState {
1098 Absent,
1099 Active,
1100 Paused,
1101}
1102
1103#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1104#[serde(rename_all = "snake_case")]
1105pub enum PlatformVaultSessionState {
1106 Absent,
1107 Active,
1108 Expired,
1109}
1110
1111#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1112#[serde(rename_all = "snake_case")]
1113pub enum PlatformVaultWithdrawalMode {
1114 Unrestricted,
1115 Blocked,
1116 Restricted,
1117}
1118
1119#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1122#[serde(deny_unknown_fields)]
1123pub struct PlatformVaultSpendingLimit {
1124 pub asset_id: String,
1125 pub maximum_per_execution_atoms: Option<String>,
1126}
1127
1128#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1131#[serde(deny_unknown_fields)]
1132pub struct PlatformVaultSessionStatus {
1133 pub session_public_key: String,
1134 pub state: PlatformVaultSessionState,
1135 pub expires_at_ms: Option<u64>,
1136 pub permanent: bool,
1137 pub minimum_interval_seconds: u32,
1138 pub maximum_tolerance_bps: u16,
1139 pub last_execution_at_ms: Option<u64>,
1140 pub market_execution_ready: bool,
1141 pub price_protection_active: bool,
1142 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1143}
1144
1145#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1146#[serde(deny_unknown_fields)]
1147pub struct PlatformVaultWithdrawalAccess {
1148 pub mode: PlatformVaultWithdrawalMode,
1149 pub allowed_wallet_addresses: Vec<String>,
1150}
1151
1152#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1155#[serde(deny_unknown_fields)]
1156pub struct PlatformVaultStatusResponse {
1157 pub schema_version: u16,
1158 pub contract_version: String,
1159 pub server_time_ms: u64,
1160 pub wallet_address: String,
1161 pub state: PlatformVaultState,
1162 pub session: Option<PlatformVaultSessionStatus>,
1163 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1164}
1165
1166#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1167#[serde(deny_unknown_fields)]
1168pub struct PlatformVaultPausePrepareRequest {
1169 pub wallet_address: String,
1170 pub paused: bool,
1171}
1172
1173#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1176#[serde(deny_unknown_fields)]
1177pub struct PlatformVaultPausePrepareResponse {
1178 pub schema_version: u16,
1179 pub contract_version: String,
1180 pub server_time_ms: u64,
1181 pub wallet_address: String,
1182 pub paused: bool,
1183 pub transaction_base64: String,
1184 pub recent_blockhash: String,
1185 pub owner_signature_required: bool,
1186 pub preparation_id: String,
1190 pub sponsored: bool,
1194 pub submit_by_ms: u64,
1196}
1197
1198#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1199#[serde(rename_all = "snake_case")]
1200pub enum PlatformVaultSetupMode {
1201 Create,
1202 ReplaceSession,
1203}
1204
1205pub const PLATFORM_SESSION_DEFAULT_MINIMUM_INTERVAL_SECONDS: u32 = 1;
1208pub const PLATFORM_SESSION_DEFAULT_MAXIMUM_TOLERANCE_BPS: u16 = 100;
1209pub const PLATFORM_SESSION_MAX_SPENDING_LIMITS: usize = 4;
1211
1212#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1216#[serde(deny_unknown_fields)]
1217pub struct PlatformVaultSetupPrepareRequest {
1218 pub wallet_address: String,
1219 pub session_public_key: String,
1220 #[serde(default)]
1223 pub market_id: Option<String>,
1224 #[serde(default)]
1227 pub expires_at_ms: Option<u64>,
1228 #[serde(default)]
1230 pub minimum_interval_seconds: Option<u32>,
1231 #[serde(default)]
1233 pub maximum_tolerance_bps: Option<u16>,
1234 #[serde(default)]
1237 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1238}
1239
1240#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1243#[serde(deny_unknown_fields)]
1244pub struct PlatformVaultSetupPrepareResponse {
1245 pub schema_version: u16,
1246 pub contract_version: String,
1247 pub server_time_ms: u64,
1248 pub wallet_address: String,
1249 pub session_public_key: String,
1250 pub market_id: Option<String>,
1252 pub mode: PlatformVaultSetupMode,
1253 pub expires_at_ms: Option<u64>,
1254 pub permanent: bool,
1255 pub minimum_interval_seconds: u32,
1257 pub maximum_tolerance_bps: u16,
1258 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1259 pub transaction_base64: String,
1260 pub recent_blockhash: String,
1261 pub owner_signature_required: bool,
1262 pub preparation_id: String,
1266 pub sponsored: bool,
1270 pub submit_by_ms: u64,
1272}
1273
1274#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1275#[serde(rename_all = "snake_case")]
1276pub enum PlatformVaultDelegateAction {
1277 Revoke,
1278}
1279
1280#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1281#[serde(deny_unknown_fields)]
1282pub struct PlatformVaultDelegatePrepareRequest {
1283 pub wallet_address: String,
1284 pub session_public_key: String,
1285 pub action: PlatformVaultDelegateAction,
1286}
1287
1288#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1291#[serde(deny_unknown_fields)]
1292pub struct PlatformVaultDelegatePrepareResponse {
1293 pub schema_version: u16,
1294 pub contract_version: String,
1295 pub server_time_ms: u64,
1296 pub wallet_address: String,
1297 pub session_public_key: String,
1298 pub action: PlatformVaultDelegateAction,
1299 pub transaction_base64: String,
1300 pub recent_blockhash: String,
1301 pub owner_signature_required: bool,
1302 pub preparation_id: String,
1306 pub sponsored: bool,
1310 pub submit_by_ms: u64,
1312}
1313
1314#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1315#[serde(deny_unknown_fields)]
1316pub struct PlatformVaultPolicyPrepareRequest {
1317 pub wallet_address: String,
1318 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1319}
1320
1321#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1324#[serde(deny_unknown_fields)]
1325pub struct PlatformVaultPolicyPrepareResponse {
1326 pub schema_version: u16,
1327 pub contract_version: String,
1328 pub server_time_ms: u64,
1329 pub wallet_address: String,
1330 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1331 pub transaction_base64: String,
1332 pub recent_blockhash: String,
1333 pub owner_signature_required: bool,
1334 pub preparation_id: String,
1338 pub sponsored: bool,
1342 pub submit_by_ms: u64,
1344}
1345
1346#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1347#[serde(deny_unknown_fields)]
1348pub struct PlatformVaultDepositPrepareRequest {
1349 pub wallet_address: String,
1350 pub market_id: String,
1351 pub asset_id: String,
1352 pub amount_atoms: String,
1353 #[serde(default)]
1358 pub session_public_key: Option<String>,
1359}
1360
1361#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1364#[serde(deny_unknown_fields)]
1365pub struct PlatformVaultDepositPrepareResponse {
1366 pub schema_version: u16,
1367 pub contract_version: String,
1368 pub server_time_ms: u64,
1369 pub wallet_address: String,
1370 pub market_id: String,
1371 pub asset_id: String,
1372 pub amount_atoms: String,
1373 pub network_cost_atoms: String,
1379 pub session_public_key: Option<String>,
1381 pub registers_session: bool,
1385 pub transaction_base64: String,
1386 pub recent_blockhash: String,
1387 pub owner_signature_required: bool,
1388 pub preparation_id: String,
1392 pub sponsored: bool,
1396 pub submit_by_ms: u64,
1398}
1399
1400#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1401#[serde(deny_unknown_fields)]
1402pub struct PlatformVaultWithdrawPrepareRequest {
1403 pub wallet_address: String,
1404 pub market_id: String,
1405 pub asset_id: String,
1406 pub destination_wallet_address: String,
1407 pub amount_atoms: String,
1408}
1409
1410#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1413#[serde(deny_unknown_fields)]
1414pub struct PlatformVaultWithdrawPrepareResponse {
1415 pub schema_version: u16,
1416 pub contract_version: String,
1417 pub server_time_ms: u64,
1418 pub wallet_address: String,
1419 pub market_id: String,
1420 pub asset_id: String,
1421 pub destination_wallet_address: String,
1422 pub amount_atoms: String,
1423 pub transaction_base64: String,
1424 pub recent_blockhash: String,
1425 pub owner_signature_required: bool,
1426 pub preparation_id: String,
1430 pub sponsored: bool,
1434 pub submit_by_ms: u64,
1436}
1437
1438#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1440#[serde(rename_all = "snake_case")]
1441pub enum PlatformVaultAction {
1442 Setup,
1443 Deposit,
1444 Withdraw,
1445 Delegate,
1446 Policy,
1447 Pause,
1448}
1449
1450#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1451#[serde(rename_all = "snake_case")]
1452pub enum PlatformVaultSubmissionStatus {
1453 Submitted,
1455 Confirmed,
1456 Failed,
1457}
1458
1459#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1464#[serde(deny_unknown_fields)]
1465pub struct PlatformVaultSubmitRequest {
1466 pub preparation_id: String,
1467 pub signed_transaction_base64: String,
1468 pub idempotency_key: String,
1469}
1470
1471#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1473#[serde(deny_unknown_fields)]
1474pub struct PlatformVaultSubmitResponse {
1475 pub schema_version: u16,
1476 pub contract_version: String,
1477 pub preparation_id: String,
1478 pub action: PlatformVaultAction,
1479 pub wallet_address: String,
1480 pub sponsored: bool,
1481 pub signature: String,
1482 pub status: PlatformVaultSubmissionStatus,
1483 pub failure_code: Option<String>,
1485 pub updated_at_ms: u64,
1486}
1487
1488#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1489#[serde(deny_unknown_fields)]
1490pub struct PlatformRewardStanding {
1491 pub rank: u32,
1492 pub wallet_address: String,
1493 pub points: String,
1494}
1495
1496#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1497#[serde(deny_unknown_fields)]
1498pub struct PlatformOwnerRewards {
1499 pub wallet_address: String,
1500 pub rank: Option<u32>,
1501 pub points: String,
1502 pub trading_points: String,
1503 pub making_points: String,
1504 pub bug_points: String,
1505 pub referral_points: String,
1506}
1507
1508#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1509#[serde(deny_unknown_fields)]
1510pub struct PlatformRewardsResponse {
1511 pub schema_version: u16,
1512 pub contract_version: String,
1513 pub server_time_ms: u64,
1514 pub season: String,
1515 pub total_wallets: u32,
1516 pub owner: Option<PlatformOwnerRewards>,
1517 pub standings: Vec<PlatformRewardStanding>,
1518}
1519
1520#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1521#[serde(deny_unknown_fields)]
1522pub struct PlatformReferralsResponse {
1523 pub schema_version: u16,
1524 pub contract_version: String,
1525 pub server_time_ms: u64,
1526 pub wallet_address: String,
1527 pub enabled: bool,
1528 pub cash_rewards_enabled: bool,
1529 pub referral_code: Option<String>,
1530 pub referred_wallets: u32,
1531 pub referral_points: String,
1532 pub referred_by: Option<String>,
1533 pub referral_locked: bool,
1534 pub cash_accrued_atoms: String,
1535 pub cash_paid_atoms: String,
1536 pub cash_claimable_atoms: String,
1537}
1538
1539#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1540#[serde(deny_unknown_fields)]
1541pub struct PlatformReferralLinkRequest {
1542 pub wallet_address: String,
1543 pub referral_code: String,
1544 pub authorization_signature: String,
1545}
1546
1547#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1548#[serde(deny_unknown_fields)]
1549pub struct PlatformReferralLinkResponse {
1550 pub schema_version: u16,
1551 pub contract_version: String,
1552 pub server_time_ms: u64,
1553 pub wallet_address: String,
1554 pub referral_code: String,
1555 pub status: String,
1556}
1557
1558#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1559#[serde(deny_unknown_fields)]
1560pub struct PlatformReferralClaimRequest {
1561 pub wallet_address: String,
1562 pub payout_wallet_address: Option<String>,
1563 pub authorization_signature: String,
1564}
1565
1566#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1567#[serde(deny_unknown_fields)]
1568pub struct PlatformReferralClaimResponse {
1569 pub schema_version: u16,
1570 pub contract_version: String,
1571 pub server_time_ms: u64,
1572 pub wallet_address: String,
1573 pub payout_wallet_address: String,
1574 pub claimable_atoms: String,
1575 pub status: String,
1576}
1577
1578#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1579#[serde(rename_all = "snake_case")]
1580pub enum PlatformBugStatus {
1581 Pending,
1582 Confirmed,
1583 Rejected,
1584}
1585
1586#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1587#[serde(deny_unknown_fields)]
1588pub struct PlatformBugReport {
1589 pub bug_id: String,
1590 pub status: PlatformBugStatus,
1591 pub severity: u8,
1592 pub points: String,
1593 pub created_at_ms: u64,
1594 pub triaged_at_ms: Option<u64>,
1595 pub completed_at_ms: Option<u64>,
1596}
1597
1598#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1599#[serde(deny_unknown_fields)]
1600pub struct PlatformBugsResponse {
1601 pub schema_version: u16,
1602 pub contract_version: String,
1603 pub server_time_ms: u64,
1604 pub wallet_address: String,
1605 pub points: String,
1606 pub confirmed_reports: u32,
1607 pub reports: Vec<PlatformBugReport>,
1608}
1609
1610#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1611#[serde(deny_unknown_fields)]
1612pub struct PlatformBugSubmitRequest {
1613 pub owner_wallet: String,
1614 pub message: String,
1615 pub authorization_signature: String,
1618}
1619
1620#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1621#[serde(deny_unknown_fields)]
1622pub struct PlatformBugSubmitResponse {
1623 pub schema_version: u16,
1624 pub contract_version: String,
1625 pub server_time_ms: u64,
1626 pub bug_id: String,
1627 pub status: PlatformBugStatus,
1628}
1629
1630#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1631#[serde(rename_all = "snake_case")]
1632pub enum PlatformTradeSide {
1633 Buy,
1634 Sell,
1635}
1636
1637#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1638#[serde(deny_unknown_fields)]
1639pub struct PlatformTrade {
1640 pub trade_id: String,
1641 pub side: PlatformTradeSide,
1642 pub price_atoms: String,
1643 pub size_atoms: String,
1644 pub executed_at_ms: u64,
1645}
1646
1647#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1648#[serde(deny_unknown_fields)]
1649pub struct PlatformTradesResponse {
1650 pub schema_version: u16,
1651 pub contract_version: String,
1652 pub market_id: String,
1653 pub server_time_ms: u64,
1654 pub trades: Vec<PlatformTrade>,
1655}
1656
1657#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1658#[serde(rename_all = "snake_case")]
1659pub enum PlatformOrderType {
1660 GoodUntilCancelled,
1661 ImmediateOrCancel,
1662 FillOrKill,
1663 PostOnly,
1664}
1665
1666#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1670#[serde(rename_all = "snake_case")]
1671pub enum PlatformOrderAction {
1672 Place,
1673 Cancel,
1674 CancelAll,
1675 Replace,
1678 Batch,
1681}
1682
1683#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1686#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
1687pub enum PlatformOrderBatchOperation {
1688 Place {
1689 #[serde(default, skip_serializing_if = "Option::is_none")]
1695 account_sequence: Option<String>,
1696 client_order_id: String,
1697 side: PlatformTradeSide,
1698 order_type: PlatformOrderType,
1699 limit_price_atoms: String,
1700 size_atoms: String,
1701 },
1702 Cancel {
1703 order_id: String,
1704 },
1705 Replace {
1706 order_id: String,
1707 #[serde(default, skip_serializing_if = "Option::is_none")]
1708 account_sequence: Option<String>,
1709 client_order_id: String,
1710 side: PlatformTradeSide,
1711 order_type: PlatformOrderType,
1712 limit_price_atoms: String,
1713 size_atoms: String,
1714 },
1715}
1716
1717#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1721#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
1722pub enum PlatformOrderChallengeRequest {
1723 Place {
1724 owner_wallet: String,
1725 session_public_key: String,
1726 #[serde(default, skip_serializing_if = "Option::is_none")]
1730 account_sequence: Option<String>,
1731 client_order_id: String,
1732 side: PlatformTradeSide,
1733 order_type: PlatformOrderType,
1734 limit_price_atoms: String,
1735 size_atoms: String,
1736 },
1737 Cancel {
1738 owner_wallet: String,
1739 session_public_key: String,
1740 order_id: String,
1741 },
1742 CancelAll {
1743 owner_wallet: String,
1744 session_public_key: String,
1745 },
1746 Replace {
1747 owner_wallet: String,
1748 session_public_key: String,
1749 order_id: String,
1750 #[serde(default, skip_serializing_if = "Option::is_none")]
1751 account_sequence: Option<String>,
1752 client_order_id: String,
1753 side: PlatformTradeSide,
1754 order_type: PlatformOrderType,
1755 limit_price_atoms: String,
1756 size_atoms: String,
1757 },
1758 Batch {
1759 owner_wallet: String,
1760 session_public_key: String,
1761 operations: Vec<PlatformOrderBatchOperation>,
1762 },
1763}
1764
1765#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1766#[serde(deny_unknown_fields)]
1767pub struct PlatformOrderChallengeResponse {
1768 pub schema_version: u16,
1769 pub contract_version: String,
1770 pub challenge_id: String,
1771 pub market_id: String,
1772 pub action: PlatformOrderAction,
1773 pub order_ids: Vec<String>,
1777 pub authorization_payload_base64: String,
1778 pub server_time_ms: u64,
1779 pub expires_at_ms: u64,
1780}
1781
1782#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1784#[serde(deny_unknown_fields)]
1785pub struct PlatformOrderPrepareAuthorization {
1786 pub challenge_id: String,
1787 #[serde(default, skip_serializing_if = "Option::is_none")]
1792 pub authorization_signature: Option<String>,
1793}
1794
1795#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1801#[serde(untagged)]
1802pub enum PlatformOrderPrepareRequest {
1803 Authorized(PlatformOrderPrepareAuthorization),
1804 Direct(PlatformOrderChallengeRequest),
1805}
1806
1807#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1808#[serde(deny_unknown_fields)]
1809pub struct PlatformOrderPrepareResponse {
1810 pub schema_version: u16,
1811 pub contract_version: String,
1812 pub order_control_id: String,
1813 pub market_id: String,
1814 pub action: PlatformOrderAction,
1815 pub order_ids: Vec<String>,
1816 pub transaction_base64: String,
1819 pub recent_blockhash: String,
1820 pub last_valid_block_height: u64,
1821 pub expires_at_ms: u64,
1822}
1823
1824#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1825#[serde(deny_unknown_fields)]
1826pub struct PlatformOrderSubmitRequest {
1827 pub order_control_id: String,
1828 pub signed_transaction_base64: String,
1829 pub idempotency_key: String,
1830}
1831
1832#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1833#[serde(rename_all = "snake_case")]
1834pub enum PlatformOrderSubmissionStatus {
1835 Submitted,
1836}
1837
1838#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1839#[serde(deny_unknown_fields)]
1840pub struct PlatformOrderSubmitResponse {
1841 pub schema_version: u16,
1842 pub contract_version: String,
1843 pub order_control_id: String,
1844 pub market_id: String,
1845 pub action: PlatformOrderAction,
1846 pub order_ids: Vec<String>,
1847 pub signature: String,
1848 pub status: PlatformOrderSubmissionStatus,
1849}
1850
1851#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1852#[serde(deny_unknown_fields)]
1853pub struct PlatformOrderStatusRequest {
1854 pub order_control_id: String,
1855 pub idempotency_key: String,
1856}
1857
1858#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1859#[serde(rename_all = "snake_case")]
1860pub enum PlatformOrderControlStatus {
1861 Submitting,
1862 Submitted,
1863 Failed,
1864}
1865
1866#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1867#[serde(deny_unknown_fields)]
1868pub struct PlatformOrderStatusResponse {
1869 pub schema_version: u16,
1870 pub contract_version: String,
1871 pub order_control_id: String,
1872 pub market_id: String,
1873 pub action: PlatformOrderAction,
1874 pub order_ids: Vec<String>,
1875 pub signature: String,
1876 pub status: PlatformOrderControlStatus,
1877 pub failure_code: Option<String>,
1878 pub updated_at_ms: u64,
1879}
1880
1881#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1885#[serde(rename_all = "snake_case")]
1886pub enum PlatformSelfTradePrevention {
1887 CancelTaker,
1888 CancelMaker,
1889 CancelBoth,
1890 SkipOwnLiquidity,
1891}
1892
1893#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1897#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1898pub enum PlatformOrderCommand {
1899 Probe {
1901 nonce: String,
1902 },
1903 Challenge {
1904 request: PlatformOrderChallengeRequest,
1905 self_trade_prevention: PlatformSelfTradePrevention,
1906 },
1907 Prepare {
1908 request: PlatformOrderPrepareRequest,
1909 },
1910 Submit {
1911 request: PlatformOrderSubmitRequest,
1912 },
1913 Status {
1914 request: PlatformOrderStatusRequest,
1915 },
1916 DeadManArm {
1917 timeout_ms: u64,
1918 request: PlatformOrderSubmitRequest,
1919 },
1920 DeadManStatus,
1921 DeadManHeartbeat,
1922 DeadManDisarm,
1923}
1924
1925#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1932#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1933pub enum PlatformOrderCommandClientFrame {
1934 Authenticate {
1935 owner_wallet: String,
1936 session_public_key: String,
1937 signature: String,
1939 #[serde(default, skip_serializing_if = "Option::is_none")]
1942 batch_format: Option<PlatformOrderCommandBatchFormat>,
1943 },
1944 Command {
1945 request_id: String,
1946 sequence: String,
1947 command: PlatformOrderCommand,
1948 },
1949}
1950
1951#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1952#[serde(rename_all = "snake_case")]
1953pub enum PlatformOrderCommandBatchFormat {
1954 CompactV1,
1955}
1956
1957#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1961#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1962pub enum PlatformOrderCommandBatchEvent {
1963 ProbeResult {
1964 request_id: String,
1965 nonce: String,
1966 },
1967 ChallengeResult {
1968 request_id: String,
1969 self_trade_prevention: PlatformSelfTradePrevention,
1970 prevented_order_ids: Vec<String>,
1971 effective_request: PlatformOrderChallengeRequest,
1972 response: PlatformOrderChallengeResponse,
1973 },
1974 PrepareResult {
1975 request_id: String,
1976 response: PlatformOrderPrepareResponse,
1977 },
1978 SubmitResult {
1979 request_id: String,
1980 response: PlatformOrderSubmitResponse,
1981 },
1982 StatusResult {
1983 request_id: String,
1984 response: PlatformOrderStatusResponse,
1985 },
1986 DeadManResult {
1987 request_id: String,
1988 state: PlatformDeadManState,
1989 },
1990 CommandError {
1991 request_id: String,
1992 error: PublicOperationError,
1993 },
1994 Heartbeat,
1995}
1996
1997#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1998#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1999pub enum PlatformOrderCommandServerFrame {
2000 EventBatch {
2001 schema_version: u16,
2002 contract_version: String,
2003 market_id: String,
2004 stream_id: String,
2005 first_sequence: String,
2006 previous_sequence: String,
2007 server_time_ms: u64,
2008 events: Vec<PlatformOrderCommandBatchEvent>,
2009 },
2010}
2011
2012#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2013#[serde(rename_all = "snake_case")]
2014pub enum PlatformDeadManStatus {
2015 Armed,
2016 Triggering,
2017 Triggered,
2018 Disarmed,
2019 Expired,
2020 Failed,
2021}
2022
2023#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2024#[serde(deny_unknown_fields)]
2025pub struct PlatformDeadManState {
2026 pub status: PlatformDeadManStatus,
2027 pub timeout_ms: u64,
2028 pub heartbeat_deadline_ms: u64,
2029 pub order_control_id: Option<String>,
2030 pub signature: Option<String>,
2031 pub failure_code: Option<String>,
2032 pub updated_at_ms: u64,
2033}
2034
2035#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2041#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2042pub enum PlatformOrderCommandEvent {
2043 AuthChallenge {
2044 schema_version: u16,
2045 contract_version: String,
2046 market_id: String,
2047 challenge: String,
2048 server_time_ms: u64,
2049 expires_at_ms: u64,
2050 },
2051 Ready {
2052 schema_version: u16,
2053 contract_version: String,
2054 market_id: String,
2055 stream_id: String,
2056 sequence: String,
2057 server_time_ms: u64,
2058 },
2059 ProbeResult {
2060 schema_version: u16,
2061 contract_version: String,
2062 market_id: String,
2063 stream_id: String,
2064 sequence: String,
2065 previous_sequence: String,
2066 request_id: String,
2067 nonce: String,
2068 server_time_ms: u64,
2069 },
2070 ChallengeResult {
2071 schema_version: u16,
2072 contract_version: String,
2073 market_id: String,
2074 stream_id: String,
2075 sequence: String,
2076 previous_sequence: String,
2077 request_id: String,
2078 self_trade_prevention: PlatformSelfTradePrevention,
2079 prevented_order_ids: Vec<String>,
2080 effective_request: PlatformOrderChallengeRequest,
2081 response: PlatformOrderChallengeResponse,
2082 server_time_ms: u64,
2083 },
2084 PrepareResult {
2085 schema_version: u16,
2086 contract_version: String,
2087 market_id: String,
2088 stream_id: String,
2089 sequence: String,
2090 previous_sequence: String,
2091 request_id: String,
2092 response: PlatformOrderPrepareResponse,
2093 server_time_ms: u64,
2094 },
2095 SubmitResult {
2096 schema_version: u16,
2097 contract_version: String,
2098 market_id: String,
2099 stream_id: String,
2100 sequence: String,
2101 previous_sequence: String,
2102 request_id: String,
2103 response: PlatformOrderSubmitResponse,
2104 server_time_ms: u64,
2105 },
2106 StatusResult {
2107 schema_version: u16,
2108 contract_version: String,
2109 market_id: String,
2110 stream_id: String,
2111 sequence: String,
2112 previous_sequence: String,
2113 request_id: String,
2114 response: PlatformOrderStatusResponse,
2115 server_time_ms: u64,
2116 },
2117 DeadManResult {
2118 schema_version: u16,
2119 contract_version: String,
2120 market_id: String,
2121 stream_id: String,
2122 sequence: String,
2123 previous_sequence: String,
2124 request_id: String,
2125 state: PlatformDeadManState,
2126 server_time_ms: u64,
2127 },
2128 CommandError {
2129 schema_version: u16,
2130 contract_version: String,
2131 market_id: String,
2132 stream_id: String,
2133 sequence: String,
2134 previous_sequence: String,
2135 request_id: String,
2136 error: PublicOperationError,
2137 server_time_ms: u64,
2138 },
2139 Heartbeat {
2140 schema_version: u16,
2141 contract_version: String,
2142 market_id: String,
2143 stream_id: String,
2144 sequence: String,
2145 previous_sequence: String,
2146 server_time_ms: u64,
2147 },
2148}
2149
2150#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2151#[serde(deny_unknown_fields)]
2152pub struct PlatformAccountOrder {
2153 pub order_id: String,
2154 pub side: PlatformTradeSide,
2155 pub order_type: PlatformOrderType,
2156 pub state: PlatformOrderState,
2157 pub limit_price_atoms: String,
2158 pub original_size_atoms: String,
2159 pub remaining_size_atoms: String,
2160}
2161
2162#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2163#[serde(deny_unknown_fields)]
2164pub struct PlatformAccountFill {
2165 pub fill_id: String,
2166 pub side: PlatformTradeSide,
2167 pub price_atoms: String,
2168 pub size_atoms: String,
2169 pub fee_quote_atoms: String,
2170 pub fee_is_final: bool,
2171 pub settlement: PlatformSettlementState,
2172 pub executed_at_ms: u64,
2173 pub confirmed_at_ms: Option<u64>,
2174 pub transaction_id: Option<String>,
2175 pub realized_pnl_quote_atoms: String,
2176}
2177
2178#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2179#[serde(deny_unknown_fields)]
2180pub struct PlatformAccountSnapshotResponse {
2181 pub schema_version: u16,
2182 pub contract_version: String,
2183 pub market_id: String,
2184 pub wallet_address: String,
2185 pub server_time_ms: u64,
2186 pub orders: Vec<PlatformAccountOrder>,
2187 pub fills: Vec<PlatformAccountFill>,
2188}
2189
2190#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2191#[serde(rename_all = "snake_case")]
2192pub enum PlatformMakerReputationTier {
2193 Probation,
2194 Bronze,
2195 Silver,
2196 Gold,
2197 Platinum,
2198}
2199
2200#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2201#[serde(deny_unknown_fields)]
2202pub struct PlatformMakerTierProgress {
2203 pub next_tier: Option<PlatformMakerReputationTier>,
2204 pub reputation_score_required: Option<u16>,
2205 pub reputation_score_remaining: u16,
2206 pub quote_requests_required: Option<String>,
2207 pub quote_requests_remaining: String,
2208 pub stake_atoms_required: Option<String>,
2209 pub stake_atoms_remaining: String,
2210 pub tenure_slots_required: Option<String>,
2211 pub tenure_slots_remaining: String,
2212}
2213
2214#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2218#[serde(deny_unknown_fields)]
2219pub struct PlatformMakerReputationResponse {
2220 pub schema_version: u16,
2221 pub contract_version: String,
2222 pub market_id: String,
2223 pub maker_id: String,
2224 pub wallet_address: String,
2225 pub active: bool,
2226 pub tier: PlatformMakerReputationTier,
2227 pub reputation_score: u16,
2228 pub total_quote_requests: String,
2229 pub successful_fills: String,
2230 pub missed_quote_requests: String,
2231 pub fill_rate_bps: u16,
2232 pub consecutive_misses: u16,
2233 pub lifetime_filled_quote_atoms: String,
2234 pub distinct_counterparties: u16,
2235 pub recent_average_latency_ms: u16,
2236 pub configured_minimum_spread_bps: u16,
2237 pub weighted_average_spread_bps: u16,
2238 pub stake_atoms: String,
2239 pub epoch_start_stake_atoms: String,
2240 pub epoch_slashed_atoms: String,
2241 pub epoch_slashed_bps: u16,
2242 pub lifetime_auto_slashed_atoms: String,
2243 pub registered_slot: String,
2244 pub last_active_slot: String,
2245 pub last_settled_slot: String,
2246 pub revoked_at_slot: Option<String>,
2247 pub tenure_slots: String,
2248 pub signed_quote_stream_eligible: bool,
2249 pub minimum_quote_interval_ms: Option<u16>,
2250 pub tier_progress: PlatformMakerTierProgress,
2251 pub server_time_ms: u64,
2252}
2253
2254#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2255#[serde(rename_all = "snake_case")]
2256pub enum PlatformMakerSide {
2257 Buy,
2258 Sell,
2259}
2260
2261#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2262#[serde(rename_all = "snake_case")]
2263pub enum PlatformOracleHealth {
2264 Fresh,
2265 Stale,
2266 Unknown,
2267}
2268
2269#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2271#[serde(deny_unknown_fields)]
2272pub struct PlatformMakerFirmOrderSummary {
2273 pub resting_orders: u32,
2274 pub bid_orders: u32,
2275 pub ask_orders: u32,
2276 pub bid_size_atoms: String,
2277 pub ask_size_atoms: String,
2278}
2279
2280#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2282#[serde(deny_unknown_fields)]
2283pub struct PlatformMakerSignedQuote {
2284 pub side: PlatformMakerSide,
2285 pub price_atoms: String,
2286 pub size_atoms: String,
2287 pub nonce: String,
2288 pub issued_at_ms: u64,
2289 pub expires_at_ms: u64,
2290}
2291
2292#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2294#[serde(deny_unknown_fields)]
2295pub struct PlatformMakerIntentStatus {
2296 pub active: bool,
2297 pub side: PlatformMakerSide,
2298 pub minimum_price_atoms: String,
2299 pub maximum_price_atoms: String,
2300 pub maximum_fill_size_atoms: String,
2301 pub remaining_fill_size_atoms: String,
2303 pub minimum_spread_bps: u16,
2304 pub stake_atoms: String,
2305}
2306
2307#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2309#[serde(deny_unknown_fields)]
2310pub struct PlatformMakerSignedQuoteLane {
2311 pub eligible: bool,
2312 pub live_quotes: Vec<PlatformMakerSignedQuote>,
2313}
2314
2315#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2316#[serde(deny_unknown_fields)]
2317pub struct PlatformMakerStrandLevel {
2318 pub price_atoms: Option<String>,
2320 pub size_atoms: String,
2321 pub remaining_size_atoms: String,
2322}
2323
2324#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2326#[serde(deny_unknown_fields)]
2327pub struct PlatformMakerStrandStatus {
2328 pub enabled: bool,
2329 pub async_only: bool,
2330 pub expired: bool,
2332 pub mid_price_atoms: String,
2333 pub tick_size_atoms: String,
2334 pub valid_until_slot: Option<String>,
2336 pub bids: Vec<PlatformMakerStrandLevel>,
2337 pub asks: Vec<PlatformMakerStrandLevel>,
2338 pub maximum_exposure_atoms: String,
2339 pub remaining_exposure_atoms: String,
2340}
2341
2342#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2344#[serde(deny_unknown_fields)]
2345pub struct PlatformMakerCurrentStatus {
2346 pub enabled: bool,
2347 pub async_only: bool,
2348 pub expired: bool,
2349 pub half_spread_bps: u16,
2350 pub band_step_bps: u16,
2351 pub maximum_confidence_bps: u16,
2352 pub maximum_oracle_age_seconds: u32,
2353 pub sync_spread_bps: u16,
2354 pub valid_until_slot: Option<String>,
2356 pub bid_depth_atoms: Vec<String>,
2357 pub ask_depth_atoms: Vec<String>,
2358 pub maximum_exposure_atoms: String,
2359 pub remaining_exposure_atoms: String,
2360 pub oracle_health: PlatformOracleHealth,
2362}
2363
2364#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2366#[serde(deny_unknown_fields)]
2367pub struct PlatformMakerDeadManGuard {
2368 pub session_public_key: String,
2369 pub status: PlatformDeadManStatus,
2370 pub timeout_ms: u64,
2371 pub heartbeat_deadline_ms: u64,
2372 pub updated_at_ms: u64,
2373}
2374
2375#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2380#[serde(deny_unknown_fields)]
2381pub struct PlatformMakerStatusResponse {
2382 pub schema_version: u16,
2383 pub contract_version: String,
2384 pub market_id: String,
2385 pub maker_id: String,
2386 pub wallet_address: String,
2387 pub server_time_ms: u64,
2388 pub current_slot: String,
2389 pub firm_orders: PlatformMakerFirmOrderSummary,
2390 pub intent: Option<PlatformMakerIntentStatus>,
2391 pub signed_quotes: PlatformMakerSignedQuoteLane,
2392 pub strands: Vec<PlatformMakerStrandStatus>,
2393 pub currents: Vec<PlatformMakerCurrentStatus>,
2394 pub dead_man_guards: Vec<PlatformMakerDeadManGuard>,
2395 pub active_products: u16,
2398}
2399
2400#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2403#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
2404pub enum PlatformMakerStrandPrepareRequest {
2405 Upsert {
2406 maker_wallet: String,
2407 enabled: bool,
2408 async_only: bool,
2409 sync_spread_ticks: u16,
2410 mid_price_atoms: String,
2411 max_exposure_base_lots: String,
2412 bid_offsets_ticks: Vec<u16>,
2413 ask_offsets_ticks: Vec<u16>,
2414 bid_sizes_base_lots: Vec<String>,
2415 ask_sizes_base_lots: Vec<String>,
2416 valid_until_slot: String,
2417 },
2418 Recenter {
2419 maker_wallet: String,
2420 new_mid_price_atoms: String,
2421 valid_until_slot: String,
2422 },
2423 SetEnabled {
2424 maker_wallet: String,
2425 enabled: bool,
2426 },
2427 Cancel {
2428 maker_wallet: String,
2429 },
2430}
2431
2432#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2435#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
2436pub enum PlatformMakerCurrentPrepareRequest {
2437 Upsert {
2438 maker_wallet: String,
2439 enabled: bool,
2440 async_only: bool,
2441 half_spread_bps: u16,
2442 band_step_bps: u16,
2443 max_conf_bps: u16,
2444 max_oracle_dev_bps: u16,
2445 max_oracle_age_secs: u32,
2446 sync_spread_bps: u16,
2447 max_exposure_base_atoms: String,
2448 bid_depth_base_atoms: Vec<String>,
2449 ask_depth_base_atoms: Vec<String>,
2450 valid_until_slot: String,
2451 },
2452 Cancel {
2453 maker_wallet: String,
2454 },
2455}
2456
2457#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2458#[serde(rename_all = "snake_case")]
2459pub enum PlatformMakerControlProduct {
2460 Strand,
2461 Current,
2462}
2463
2464#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2465#[serde(rename_all = "snake_case")]
2466pub enum PlatformMakerControlAction {
2467 StrandUpsert,
2468 StrandRecenter,
2469 StrandSetEnabled,
2470 StrandCancel,
2471 CurrentUpsert,
2472 CurrentCancel,
2473}
2474
2475#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2476#[serde(deny_unknown_fields)]
2477pub struct PlatformMakerControlPrepareResponse {
2478 pub schema_version: u16,
2479 pub contract_version: String,
2480 pub maker_control_id: String,
2481 pub market_id: String,
2482 pub maker_wallet: String,
2483 pub product: PlatformMakerControlProduct,
2484 pub action: PlatformMakerControlAction,
2485 pub transaction_base64: String,
2488 pub recent_blockhash: String,
2489 pub last_valid_block_height: u64,
2490 pub expires_at_ms: u64,
2491}
2492
2493#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2494#[serde(deny_unknown_fields)]
2495pub struct PlatformMakerControlSubmitRequest {
2496 pub maker_control_id: String,
2497 pub signed_transaction_base64: String,
2498 pub idempotency_key: String,
2499}
2500
2501#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2502#[serde(rename_all = "snake_case")]
2503pub enum PlatformMakerControlSubmissionStatus {
2504 Submitted,
2505}
2506
2507#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2508#[serde(deny_unknown_fields)]
2509pub struct PlatformMakerControlSubmitResponse {
2510 pub schema_version: u16,
2511 pub contract_version: String,
2512 pub maker_control_id: String,
2513 pub market_id: String,
2514 pub maker_wallet: String,
2515 pub product: PlatformMakerControlProduct,
2516 pub action: PlatformMakerControlAction,
2517 pub signature: String,
2518 pub status: PlatformMakerControlSubmissionStatus,
2519}
2520
2521#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2523#[serde(rename_all = "snake_case")]
2524pub enum PlatformMakerProduct {
2525 FirmOrder,
2526 Intent,
2527 Strand,
2528 Current,
2529}
2530
2531#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2534#[serde(deny_unknown_fields)]
2535pub struct PlatformMakerFill {
2536 pub fill_id: String,
2537 pub product: PlatformMakerProduct,
2538 pub side: PlatformTradeSide,
2539 pub price_atoms: String,
2540 pub size_atoms: String,
2541 pub fee_quote_atoms: String,
2542 pub fee_is_final: bool,
2543 pub settlement: PlatformSettlementState,
2544 pub executed_at_ms: u64,
2545 pub confirmed_at_ms: Option<u64>,
2546 pub transaction_id: Option<String>,
2547 pub realized_pnl_quote_atoms: String,
2548}
2549
2550#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2556#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2557pub enum PlatformMakerEvent {
2558 AuthChallenge {
2559 schema_version: u16,
2560 contract_version: String,
2561 market_id: String,
2562 wallet_address: String,
2563 challenge: String,
2564 server_time_ms: u64,
2565 expires_at_ms: u64,
2566 },
2567 MakerSnapshot {
2568 schema_version: u16,
2569 contract_version: String,
2570 market_id: String,
2571 wallet_address: String,
2572 stream_id: String,
2573 sequence: String,
2574 server_time_ms: u64,
2575 status: PlatformMakerStatusResponse,
2576 fills: Vec<PlatformMakerFill>,
2577 },
2578 MakerFill {
2579 schema_version: u16,
2580 contract_version: String,
2581 market_id: String,
2582 wallet_address: String,
2583 stream_id: String,
2584 sequence: String,
2585 previous_sequence: String,
2586 server_time_ms: u64,
2587 fill: PlatformMakerFill,
2588 },
2589 MakerStatus {
2590 schema_version: u16,
2591 contract_version: String,
2592 market_id: String,
2593 wallet_address: String,
2594 stream_id: String,
2595 sequence: String,
2596 previous_sequence: String,
2597 server_time_ms: u64,
2598 status: PlatformMakerStatusResponse,
2599 },
2600 Heartbeat {
2601 schema_version: u16,
2602 contract_version: String,
2603 market_id: String,
2604 wallet_address: String,
2605 stream_id: String,
2606 sequence: String,
2607 previous_sequence: String,
2608 server_time_ms: u64,
2609 },
2610}
2611
2612#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2613#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2614pub enum PlatformAccountEvent {
2615 AuthChallenge {
2616 schema_version: u16,
2617 contract_version: String,
2618 market_id: String,
2619 wallet_address: String,
2620 challenge: String,
2621 server_time_ms: u64,
2622 expires_at_ms: u64,
2623 },
2624 AccountSnapshot {
2625 schema_version: u16,
2626 contract_version: String,
2627 market_id: String,
2628 wallet_address: String,
2629 stream_id: String,
2630 sequence: String,
2631 server_time_ms: u64,
2632 orders: Vec<PlatformAccountOrder>,
2633 fills: Vec<PlatformAccountFill>,
2634 },
2635 OrdersSnapshot {
2636 schema_version: u16,
2637 contract_version: String,
2638 market_id: String,
2639 wallet_address: String,
2640 stream_id: String,
2641 sequence: String,
2642 previous_sequence: String,
2643 server_time_ms: u64,
2644 orders: Vec<PlatformAccountOrder>,
2645 },
2646 Fill {
2647 schema_version: u16,
2648 contract_version: String,
2649 market_id: String,
2650 wallet_address: String,
2651 stream_id: String,
2652 sequence: String,
2653 previous_sequence: String,
2654 server_time_ms: u64,
2655 fill: PlatformAccountFill,
2656 },
2657 Heartbeat {
2658 schema_version: u16,
2659 contract_version: String,
2660 market_id: String,
2661 wallet_address: String,
2662 stream_id: String,
2663 sequence: String,
2664 previous_sequence: String,
2665 server_time_ms: u64,
2666 },
2667}
2668
2669#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2670#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2671pub enum PlatformMarketDataEvent {
2672 BookSnapshot {
2673 schema_version: u16,
2674 contract_version: String,
2675 market_id: String,
2676 stream_id: String,
2677 sequence: String,
2678 server_time_ms: u64,
2679 snapshot_id: String,
2680 bids: Vec<PlatformBookLevel>,
2681 asks: Vec<PlatformBookLevel>,
2682 },
2683 BookDelta {
2684 schema_version: u16,
2685 contract_version: String,
2686 market_id: String,
2687 stream_id: String,
2688 sequence: String,
2689 previous_sequence: String,
2690 server_time_ms: u64,
2691 changes: Vec<PlatformBookChange>,
2692 },
2693 BestBidAsk {
2694 schema_version: u16,
2695 contract_version: String,
2696 market_id: String,
2697 stream_id: String,
2698 sequence: String,
2699 server_time_ms: u64,
2700 best_bid: Option<PlatformBookLevel>,
2701 best_ask: Option<PlatformBookLevel>,
2702 },
2703 Trade {
2704 schema_version: u16,
2705 contract_version: String,
2706 market_id: String,
2707 server_time_ms: u64,
2708 trade: PlatformTrade,
2709 },
2710 MarketStatus {
2711 schema_version: u16,
2712 contract_version: String,
2713 market_id: String,
2714 server_time_ms: u64,
2715 status: PlatformMarketState,
2716 },
2717 Heartbeat {
2718 schema_version: u16,
2719 contract_version: String,
2720 market_id: String,
2721 server_time_ms: u64,
2722 },
2723}
2724
2725#[cfg(test)]
2726mod tests {
2727 use super::*;
2728
2729 #[test]
2730 fn public_platform_fixtures_decode_strictly() {
2731 let discovery: PlatformDiscoveryResponse =
2732 serde_json::from_str(PLATFORM_CAPABILITIES_FIXTURE).unwrap();
2733 let service_status: PlatformServiceStatusResponse =
2734 serde_json::from_str(PLATFORM_SERVICE_STATUS_FIXTURE).unwrap();
2735 let graph = PlatformActionGraphResponse::foundation();
2736 let assets: PlatformAssetsResponse = serde_json::from_str(PLATFORM_ASSETS_FIXTURE).unwrap();
2737 let swap_quote: PlatformSwapQuoteResponse =
2738 serde_json::from_str(PLATFORM_SWAP_QUOTE_FIXTURE).unwrap();
2739 let markets: PlatformMarketsResponse =
2740 serde_json::from_str(PLATFORM_MARKETS_FIXTURE).unwrap();
2741 let book: PlatformBookSnapshotResponse =
2742 serde_json::from_str(PLATFORM_BOOK_FIXTURE).unwrap();
2743 let bbo: PlatformBestBidAskResponse = serde_json::from_str(PLATFORM_BBO_FIXTURE).unwrap();
2744 let fees: PlatformFeeScheduleResponse =
2745 serde_json::from_str(PLATFORM_FEES_FIXTURE).unwrap();
2746 let status: PlatformMarketStatusResponse =
2747 serde_json::from_str(PLATFORM_STATUS_FIXTURE).unwrap();
2748 let candles: PlatformCandlesResponse =
2749 serde_json::from_str(PLATFORM_CANDLES_FIXTURE).unwrap();
2750 let mark: PlatformMarkResponse = serde_json::from_str(PLATFORM_MARK_FIXTURE).unwrap();
2751 let execution_status: PlatformExecutionStatusResponse =
2752 serde_json::from_str(PLATFORM_EXECUTION_STATUS_FIXTURE).unwrap();
2753 let twaps: PlatformTwapsResponse = serde_json::from_str(PLATFORM_TWAPS_FIXTURE).unwrap();
2754 let twap_challenge: PlatformTwapChallengeResponse =
2755 serde_json::from_str(PLATFORM_TWAP_CHALLENGE_FIXTURE).unwrap();
2756 let twap_prepare: PlatformTwapPrepareResponse =
2757 serde_json::from_str(PLATFORM_TWAP_PREPARE_FIXTURE).unwrap();
2758 let twap_submit: PlatformTwapSubmitResponse =
2759 serde_json::from_str(PLATFORM_TWAP_SUBMIT_FIXTURE).unwrap();
2760 let portfolio_history: PlatformPortfolioHistoryResponse =
2761 serde_json::from_str(PLATFORM_PORTFOLIO_HISTORY_FIXTURE).unwrap();
2762 let portfolio: PlatformPortfolioResponse =
2763 serde_json::from_str(PLATFORM_PORTFOLIO_FIXTURE).unwrap();
2764 let rewards: PlatformRewardsResponse =
2765 serde_json::from_str(PLATFORM_REWARDS_FIXTURE).unwrap();
2766 let referrals: PlatformReferralsResponse =
2767 serde_json::from_str(PLATFORM_REFERRALS_FIXTURE).unwrap();
2768 let referral_link: PlatformReferralLinkResponse =
2769 serde_json::from_str(PLATFORM_REFERRAL_LINK_FIXTURE).unwrap();
2770 let referral_claim: PlatformReferralClaimResponse =
2771 serde_json::from_str(PLATFORM_REFERRAL_CLAIM_FIXTURE).unwrap();
2772 let vault_status: PlatformVaultStatusResponse =
2773 serde_json::from_str(PLATFORM_VAULT_STATUS_FIXTURE).unwrap();
2774 let vault_pause: PlatformVaultPausePrepareResponse =
2775 serde_json::from_str(PLATFORM_VAULT_PAUSE_PREPARE_FIXTURE).unwrap();
2776 let vault_setup: PlatformVaultSetupPrepareResponse =
2777 serde_json::from_str(PLATFORM_VAULT_SETUP_PREPARE_FIXTURE).unwrap();
2778 let vault_delegate: PlatformVaultDelegatePrepareResponse =
2779 serde_json::from_str(PLATFORM_VAULT_DELEGATE_PREPARE_FIXTURE).unwrap();
2780 let vault_policy: PlatformVaultPolicyPrepareResponse =
2781 serde_json::from_str(PLATFORM_VAULT_POLICY_PREPARE_FIXTURE).unwrap();
2782 let vault_deposit: PlatformVaultDepositPrepareResponse =
2783 serde_json::from_str(PLATFORM_VAULT_DEPOSIT_PREPARE_FIXTURE).unwrap();
2784 let vault_withdraw: PlatformVaultWithdrawPrepareResponse =
2785 serde_json::from_str(PLATFORM_VAULT_WITHDRAW_PREPARE_FIXTURE).unwrap();
2786 let vault_submit: PlatformVaultSubmitResponse =
2787 serde_json::from_str(PLATFORM_VAULT_SUBMIT_FIXTURE).unwrap();
2788 let bugs: PlatformBugsResponse = serde_json::from_str(PLATFORM_BUGS_FIXTURE).unwrap();
2789 let bug_submit: PlatformBugSubmitResponse =
2790 serde_json::from_str(PLATFORM_BUG_SUBMIT_FIXTURE).unwrap();
2791 let trades: PlatformTradesResponse = serde_json::from_str(PLATFORM_TRADES_FIXTURE).unwrap();
2792 let account: PlatformAccountSnapshotResponse =
2793 serde_json::from_str(PLATFORM_ACCOUNT_FIXTURE).unwrap();
2794 let maker_reputation: PlatformMakerReputationResponse =
2795 serde_json::from_str(PLATFORM_MAKER_REPUTATION_FIXTURE).unwrap();
2796 let maker_status: PlatformMakerStatusResponse =
2797 serde_json::from_str(PLATFORM_MAKER_STATUS_FIXTURE).unwrap();
2798 let maker_stream: PlatformMakerEvent =
2799 serde_json::from_str(PLATFORM_MAKER_STREAM_FIXTURE).unwrap();
2800 let twap_stream: PlatformTwapEvent =
2801 serde_json::from_str(PLATFORM_TWAP_STREAM_FIXTURE).unwrap();
2802 let execution_stream: PlatformExecutionEvent =
2803 serde_json::from_str(PLATFORM_EXECUTION_STREAM_FIXTURE).unwrap();
2804 let order_challenge: PlatformOrderChallengeResponse =
2805 serde_json::from_str(PLATFORM_ORDER_CHALLENGE_FIXTURE).unwrap();
2806 let order_prepare: PlatformOrderPrepareResponse =
2807 serde_json::from_str(PLATFORM_ORDER_PREPARE_FIXTURE).unwrap();
2808 let order_submit: PlatformOrderSubmitResponse =
2809 serde_json::from_str(PLATFORM_ORDER_SUBMIT_FIXTURE).unwrap();
2810 let order_status: PlatformOrderStatusResponse =
2811 serde_json::from_str(PLATFORM_ORDER_STATUS_FIXTURE).unwrap();
2812
2813 assert_eq!(discovery.schema_version, PLATFORM_SCHEMA_VERSION);
2814 assert_eq!(service_status.status, PlatformServiceState::Operational);
2815 assert_eq!(service_status.available_operations, 59);
2816 assert_eq!(graph.entry_operation_id, "platform.capabilities.read");
2817 assert_eq!(graph.operations.len(), 69);
2818 assert_eq!(maker_reputation.tier, PlatformMakerReputationTier::Gold);
2819 assert_eq!(maker_status.active_products, 3);
2820 match &maker_stream {
2821 PlatformMakerEvent::MakerSnapshot { status, fills, .. } => {
2822 assert_eq!(status.active_products, maker_status.active_products);
2823 assert_eq!(fills.len(), 1);
2824 assert_eq!(fills[0].product, PlatformMakerProduct::Strand);
2825 }
2826 other => panic!("maker stream fixture must be a snapshot, got {other:?}"),
2827 }
2828 match &twap_stream {
2829 PlatformTwapEvent::TwapsSnapshot {
2830 twaps: streamed, ..
2831 } => {
2832 assert_eq!(streamed, &twaps.twaps);
2833 }
2834 other => panic!("twap stream fixture must be a snapshot, got {other:?}"),
2835 }
2836 match &execution_stream {
2837 PlatformExecutionEvent::ExecutionsSnapshot {
2838 executions,
2839 unknown_execution_ids,
2840 ..
2841 } => {
2842 assert_eq!(executions.len(), 2);
2843 assert_eq!(executions[0].execution_id, execution_status.execution_id);
2844 assert_eq!(unknown_execution_ids.len(), 1);
2845 }
2846 other => panic!("execution stream fixture must be a snapshot, got {other:?}"),
2847 }
2848 assert_eq!(maker_status.strands.len(), 1);
2849 assert_eq!(maker_status.currents.len(), 1);
2850 assert!(maker_status
2851 .intent
2852 .as_ref()
2853 .is_some_and(|intent| intent.active));
2854 assert_eq!(portfolio.balances.len(), 2);
2855 assert_eq!(portfolio.positions.len(), 1);
2856 assert!(portfolio.valuation_complete);
2857 assert_eq!(portfolio.equity_usd_micros.as_deref(), Some("439989500"));
2858 assert!(graph
2859 .operations
2860 .iter()
2861 .any(|operation| operation.id == "twap.place.submit"));
2862 assert!(graph
2863 .operations
2864 .iter()
2865 .any(|operation| operation.id == "twap.cancel.submit"));
2866 assert_eq!(discovery.capabilities.len(), 5);
2867 assert!(!discovery.authority.accepts_private_keys);
2868 assert_eq!(assets.assets.len(), 2);
2869 assert_eq!(swap_quote.input_asset_id, assets.assets[0].asset_id);
2870 assert_eq!(swap_quote.output_asset_id, assets.assets[1].asset_id);
2871 assert_eq!(markets.markets.len(), 1);
2872 assert_eq!(markets.markets[0].base_asset_id, assets.assets[0].asset_id);
2873 assert_eq!(markets.markets[0].quote_asset_id, assets.assets[1].asset_id);
2874 assert_eq!(book.sequence, "42");
2875 assert_eq!(bbo.best_bid.unwrap().price_atoms, "149990000");
2876 assert_eq!(fees.maximum_immediate_execution_fee_bps, 10);
2877 assert_eq!(status.status, PlatformMarketState::Active);
2878 assert_eq!(candles.candles.len(), 2);
2879 assert_eq!(mark.price_atoms_per_base_unit.as_deref(), Some("149995000"));
2880 assert_eq!(execution_status.status, PlatformExecutionState::Confirmed);
2881 assert_eq!(
2882 execution_status.settlement,
2883 PlatformSettlementState::Confirmed
2884 );
2885 assert_eq!(twaps.twaps[0].fills.len(), 1);
2886 assert_eq!(twaps.twaps[0].slices_executed, 2);
2887 assert_eq!(twap_challenge.action, PlatformTwapControlAction::Place);
2888 assert_eq!(twap_prepare.twap_id, twap_challenge.twap_id);
2889 assert_eq!(twap_submit.twap_control_id, twap_prepare.twap_control_id);
2890 assert_eq!(portfolio_history.points.len(), 2);
2891 assert_eq!(rewards.standings.len(), 2);
2892 assert!(referrals.enabled);
2893 assert_eq!(referral_link.status, "pending_first_fill");
2894 assert_eq!(referral_claim.status, "requested");
2895 assert_eq!(vault_status.state, PlatformVaultState::Active);
2896 assert_eq!(
2897 vault_status.session.as_ref().unwrap().state,
2898 PlatformVaultSessionState::Active
2899 );
2900 assert!(vault_pause.paused);
2901 assert!(vault_pause.owner_signature_required);
2902 assert_eq!(vault_setup.mode, PlatformVaultSetupMode::Create);
2903 assert!(vault_setup.permanent);
2904 assert_eq!(vault_delegate.action, PlatformVaultDelegateAction::Revoke);
2905 assert!(vault_delegate.owner_signature_required);
2906 assert_eq!(
2907 vault_policy.withdrawal_access.mode,
2908 PlatformVaultWithdrawalMode::Restricted
2909 );
2910 assert!(vault_policy.owner_signature_required);
2911 assert_eq!(vault_deposit.amount_atoms, "10000000");
2912 assert!(vault_deposit.owner_signature_required);
2913 assert_eq!(vault_withdraw.amount_atoms, "5000000");
2914 assert!(vault_withdraw.owner_signature_required);
2915 assert!(vault_withdraw.sponsored);
2916 assert!(vault_withdraw.preparation_id.starts_with("vp_"));
2917 assert_eq!(vault_submit.action, PlatformVaultAction::Deposit);
2918 assert_eq!(
2919 vault_submit.status,
2920 PlatformVaultSubmissionStatus::Submitted
2921 );
2922 assert!(vault_submit.sponsored);
2923 assert_eq!(vault_submit.failure_code, None);
2924 assert_eq!(bugs.reports[0].status, PlatformBugStatus::Confirmed);
2925 assert_eq!(bug_submit.status, PlatformBugStatus::Pending);
2926 assert_eq!(trades.trades.len(), 1);
2927 assert_eq!(account.orders.len(), 1);
2928 assert_eq!(account.fills.len(), 1);
2929 assert_eq!(order_challenge.action, PlatformOrderAction::Place);
2930 assert_eq!(order_prepare.order_ids, order_challenge.order_ids);
2931 assert_eq!(order_submit.order_ids, order_challenge.order_ids);
2932 assert_eq!(order_status.order_control_id, order_submit.order_control_id);
2933 assert_eq!(order_status.status, PlatformOrderControlStatus::Submitting);
2934 }
2935
2936 #[test]
2937 fn public_platform_response_rejects_unreviewed_fields() {
2938 let mut value: serde_json::Value =
2939 serde_json::from_str(PLATFORM_CAPABILITIES_FIXTURE).unwrap();
2940 value
2941 .as_object_mut()
2942 .unwrap()
2943 .insert("unexpected_field".to_owned(), serde_json::Value::Bool(true));
2944 assert!(serde_json::from_value::<PlatformDiscoveryResponse>(value).is_err());
2945
2946 let mut account_event: serde_json::Value =
2947 serde_json::from_str(PLATFORM_ACCOUNT_FIXTURE).unwrap();
2948 let event = account_event.as_object_mut().unwrap();
2949 event.insert("type".to_owned(), serde_json::json!("account_snapshot"));
2950 event.insert(
2951 "stream_id".to_owned(),
2952 serde_json::json!("account_stream_66666666666666666666666666666666"),
2953 );
2954 event.insert("sequence".to_owned(), serde_json::json!("1"));
2955 event.insert("unexpected_field".to_owned(), serde_json::json!(true));
2956 assert!(serde_json::from_value::<PlatformAccountEvent>(account_event).is_err());
2957 }
2958
2959 #[test]
2960 fn platform_graph_availability_is_projected_from_live_capabilities() {
2961 let mut graph = PlatformActionGraphResponse::foundation();
2962 let live = std::collections::BTreeSet::from([
2963 "platform.discover".to_owned(),
2964 "graphs.read".to_owned(),
2965 "orders.replace".to_owned(),
2966 ]);
2967
2968 graph.project_availability(&live);
2969
2970 for operation in &graph.operations {
2971 assert_eq!(
2972 operation.available,
2973 live.contains(&operation.capability_id),
2974 "operation {} did not follow capability {}",
2975 operation.id,
2976 operation.capability_id,
2977 );
2978 }
2979 assert!(graph
2980 .workflows
2981 .iter()
2982 .flat_map(|workflow| &workflow.nodes)
2983 .filter(|node| node.kind != PlatformActionKind::ExternalSignature)
2984 .all(|node| {
2985 node.available
2986 == node
2987 .capability_id
2988 .as_ref()
2989 .is_some_and(|capability_id| live.contains(capability_id))
2990 }));
2991 assert!(graph
2992 .workflows
2993 .iter()
2994 .flat_map(|workflow| &workflow.nodes)
2995 .filter(|node| node.kind == PlatformActionKind::ExternalSignature)
2996 .all(|node| node.available));
2997 }
2998
2999 #[test]
3000 fn atomic_order_batch_request_is_strict_and_typed() {
3001 let request: PlatformOrderChallengeRequest = serde_json::from_value(serde_json::json!({
3002 "action": "batch",
3003 "owner_wallet": "11111111111111111111111111111111",
3004 "session_public_key": "22222222222222222222222222222222",
3005 "operations": [
3006 {
3007 "action": "cancel",
3008 "order_id": "order_11111111111111111111111111111111"
3009 },
3010 {
3011 "action": "replace",
3012 "order_id": "order_22222222222222222222222222222222",
3013 "account_sequence": "8",
3014 "client_order_id": "replacement-8",
3015 "side": "sell",
3016 "order_type": "post_only",
3017 "limit_price_atoms": "151000000",
3018 "size_atoms": "2000000"
3019 }
3020 ]
3021 }))
3022 .unwrap();
3023 let PlatformOrderChallengeRequest::Batch { operations, .. } = request else {
3024 panic!("expected batch request");
3025 };
3026 assert_eq!(operations.len(), 2);
3027 assert!(matches!(
3028 &operations[1],
3029 PlatformOrderBatchOperation::Replace { account_sequence: Some(sequence), .. }
3030 if sequence == "8"
3031 ));
3032
3033 let place: PlatformOrderChallengeRequest = serde_json::from_value(serde_json::json!({
3037 "action": "place",
3038 "owner_wallet": "11111111111111111111111111111111",
3039 "session_public_key": "22222222222222222222222222222222",
3040 "client_order_id": "first-order",
3041 "side": "buy",
3042 "order_type": "post_only",
3043 "limit_price_atoms": "150000000",
3044 "size_atoms": "1000000"
3045 }))
3046 .unwrap();
3047 assert!(matches!(
3048 place,
3049 PlatformOrderChallengeRequest::Place {
3050 account_sequence: None,
3051 ..
3052 }
3053 ));
3054 assert!(!serde_json::to_string(&place)
3055 .unwrap()
3056 .contains("account_sequence"));
3057
3058 assert!(
3059 serde_json::from_value::<PlatformOrderChallengeRequest>(serde_json::json!({
3060 "action": "batch",
3061 "owner_wallet": "11111111111111111111111111111111",
3062 "session_public_key": "22222222222222222222222222222222",
3063 "operations": [{
3064 "action": "cancel",
3065 "order_id": "order_11111111111111111111111111111111",
3066 "implementation": "hidden"
3067 }]
3068 }))
3069 .is_err()
3070 );
3071 }
3072
3073 #[test]
3074 fn persistent_order_commands_are_strict_and_explicit_about_self_trade_policy() {
3075 let frame: PlatformOrderCommandClientFrame = serde_json::from_value(serde_json::json!({
3076 "type": "command",
3077 "request_id": "agent-1",
3078 "sequence": "1",
3079 "command": {
3080 "type": "challenge",
3081 "self_trade_prevention": "cancel_maker",
3082 "request": {
3083 "action": "cancel_all",
3084 "owner_wallet": "11111111111111111111111111111111",
3085 "session_public_key": "22222222222222222222222222222222"
3086 }
3087 }
3088 }))
3089 .unwrap();
3090 assert!(matches!(
3091 frame,
3092 PlatformOrderCommandClientFrame::Command {
3093 command: PlatformOrderCommand::Challenge {
3094 self_trade_prevention: PlatformSelfTradePrevention::CancelMaker,
3095 ..
3096 },
3097 ..
3098 }
3099 ));
3100 assert!(
3101 serde_json::from_value::<PlatformOrderCommandClientFrame>(serde_json::json!({
3102 "type": "command",
3103 "request_id": "agent-1",
3104 "sequence": "1",
3105 "command": {
3106 "type": "challenge",
3107 "request": {
3108 "action": "cancel_all",
3109 "owner_wallet": "11111111111111111111111111111111",
3110 "session_public_key": "22222222222222222222222222222222"
3111 }
3112 }
3113 }))
3114 .is_err()
3115 );
3116 }
3117
3118 #[test]
3119 fn prepare_requests_accept_a_signed_challenge_or_the_operation_itself() {
3120 let signed: PlatformOrderPrepareRequest = serde_json::from_value(serde_json::json!({
3121 "challenge_id": "oc_0123456789abcdef0123456789abcdef",
3122 "authorization_signature": "1111",
3123 }))
3124 .unwrap();
3125 assert!(matches!(signed, PlatformOrderPrepareRequest::Authorized(_)));
3126 let direct: PlatformOrderPrepareRequest = serde_json::from_value(serde_json::json!({
3127 "action": "cancel_all",
3128 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3129 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3130 }))
3131 .unwrap();
3132 assert!(matches!(
3133 direct,
3134 PlatformOrderPrepareRequest::Direct(PlatformOrderChallengeRequest::CancelAll { .. })
3135 ));
3136 assert!(
3138 serde_json::from_value::<PlatformOrderPrepareRequest>(serde_json::json!({
3139 "challenge_id": "oc_0123456789abcdef0123456789abcdef",
3140 "authorization_signature": "1111",
3141 "extra": true,
3142 }))
3143 .is_err()
3144 );
3145 let twap: PlatformTwapPrepareRequest = serde_json::from_value(serde_json::json!({
3146 "action": "cancel",
3147 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3148 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3149 "twap_id": "twap_0123456789abcdef0123456789abcdef",
3150 }))
3151 .unwrap();
3152 assert!(matches!(twap, PlatformTwapPrepareRequest::Direct(_)));
3153 let execution: crate::ExecutionPrepareRequest = serde_json::from_value(serde_json::json!({
3154 "quote_id": "quote_0123456789abcdef0123456789abcdef",
3155 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3156 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3157 }))
3158 .unwrap();
3159 assert!(matches!(
3160 execution,
3161 crate::ExecutionPrepareRequest::Direct(_)
3162 ));
3163 }
3164
3165 #[test]
3166 fn maker_control_requests_are_tagged_exact_and_amount_safe() {
3167 let strand: PlatformMakerStrandPrepareRequest = serde_json::from_value(serde_json::json!({
3168 "action": "recenter",
3169 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3170 "new_mid_price_atoms": "123000000",
3171 "valid_until_slot": "0"
3172 }))
3173 .unwrap();
3174 assert!(matches!(
3175 strand,
3176 PlatformMakerStrandPrepareRequest::Recenter { .. }
3177 ));
3178
3179 let current: PlatformMakerCurrentPrepareRequest =
3180 serde_json::from_value(serde_json::json!({
3181 "action": "cancel",
3182 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL"
3183 }))
3184 .unwrap();
3185 assert!(matches!(
3186 current,
3187 PlatformMakerCurrentPrepareRequest::Cancel { .. }
3188 ));
3189 assert!(
3190 serde_json::from_value::<PlatformMakerCurrentPrepareRequest>(serde_json::json!({
3191 "action": "cancel",
3192 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3193 "oracle_price": 123.45
3194 }))
3195 .is_err()
3196 );
3197 }
3198}