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,
618}
619
620#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
622#[serde(deny_unknown_fields)]
623pub struct PlatformCandle {
624 pub started_at_ms: u64,
625 pub open_price: String,
626 pub high_price: String,
627 pub low_price: String,
628 pub close_price: String,
629}
630
631#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
632#[serde(deny_unknown_fields)]
633pub struct PlatformCandlesResponse {
634 pub schema_version: u16,
635 pub contract_version: String,
636 pub market_id: String,
637 pub server_time_ms: u64,
638 pub resolution_seconds: u32,
639 pub candles: Vec<PlatformCandle>,
640}
641
642#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
643#[serde(deny_unknown_fields)]
644pub struct PlatformMarkResponse {
645 pub schema_version: u16,
646 pub contract_version: String,
647 pub market_id: String,
648 pub server_time_ms: u64,
649 pub price_atoms_per_base_unit: Option<String>,
650 pub quote_decimals: u8,
651 pub stale: bool,
652 pub age_ms: Option<u64>,
653}
654
655#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
656#[serde(rename_all = "snake_case")]
657pub enum PlatformExecutionState {
658 Prepared,
659 Confirmed,
660}
661
662#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
665#[serde(deny_unknown_fields)]
666pub struct PlatformExecutionStatusResponse {
667 pub schema_version: u16,
668 pub contract_version: String,
669 pub execution_id: String,
670 pub market_id: String,
671 pub status: PlatformExecutionState,
672 pub signature: Option<String>,
673 pub settlement: PlatformSettlementState,
674 pub updated_at_ms: u64,
675}
676
677#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
680#[serde(deny_unknown_fields)]
681pub struct PlatformExecutionRow {
682 pub execution_id: String,
683 pub market_id: String,
684 pub status: PlatformExecutionState,
685 pub signature: Option<String>,
686 pub settlement: PlatformSettlementState,
687 pub updated_at_ms: u64,
688}
689
690#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
693#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
694pub enum PlatformExecutionCommand {
695 Watch { execution_ids: Vec<String> },
696}
697
698#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
706#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
707pub enum PlatformExecutionEvent {
708 ExecutionsSnapshot {
709 schema_version: u16,
710 contract_version: String,
711 market_id: String,
712 stream_id: String,
713 sequence: String,
714 server_time_ms: u64,
715 executions: Vec<PlatformExecutionRow>,
716 unknown_execution_ids: Vec<String>,
717 },
718 ExecutionUpdate {
719 schema_version: u16,
720 contract_version: String,
721 market_id: String,
722 stream_id: String,
723 sequence: String,
724 previous_sequence: String,
725 server_time_ms: u64,
726 execution: PlatformExecutionRow,
727 },
728 ExecutionExpired {
729 schema_version: u16,
730 contract_version: String,
731 market_id: String,
732 stream_id: String,
733 sequence: String,
734 previous_sequence: String,
735 server_time_ms: u64,
736 execution_id: String,
737 },
738 ExecutionUnknown {
739 schema_version: u16,
740 contract_version: String,
741 market_id: String,
742 stream_id: String,
743 sequence: String,
744 previous_sequence: String,
745 server_time_ms: u64,
746 execution_id: String,
747 },
748 Heartbeat {
749 schema_version: u16,
750 contract_version: String,
751 market_id: String,
752 stream_id: String,
753 sequence: String,
754 previous_sequence: String,
755 server_time_ms: u64,
756 },
757}
758
759#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
760#[serde(rename_all = "snake_case")]
761pub enum PlatformTwapState {
762 Active,
763 Completed,
764 Cancelled,
765}
766
767#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
768#[serde(deny_unknown_fields)]
769pub struct PlatformTwapFill {
770 pub fill_id: String,
771 pub size_atoms: String,
772 pub price_atoms: String,
773 pub gross_quote_atoms: String,
774 pub base_fee_atoms: String,
775 pub quote_fee_atoms: String,
776 pub signature: Option<String>,
777 pub observed_at_ms: u64,
778}
779
780#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
781#[serde(deny_unknown_fields)]
782pub struct PlatformTwap {
783 pub twap_id: String,
784 pub side: PlatformTradeSide,
785 pub status: PlatformTwapState,
786 pub slices_total: u16,
787 pub slices_executed: u16,
788 pub interval_slots: u32,
789 pub maximum_tolerance_bps: u16,
790 pub limit_price_atoms: String,
791 pub total_size_atoms: String,
792 pub executed_size_atoms: String,
793 pub gross_quote_executed_atoms: String,
794 pub complete_execution_value: bool,
795 pub created_at_ms: u64,
796 pub completed_at_ms: Option<u64>,
797 pub placed_signature: Option<String>,
798 pub terminal_signature: Option<String>,
799 pub fills: Vec<PlatformTwapFill>,
800}
801
802#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
803#[serde(deny_unknown_fields)]
804pub struct PlatformTwapsResponse {
805 pub schema_version: u16,
806 pub contract_version: String,
807 pub market_id: String,
808 pub wallet_address: String,
809 pub server_time_ms: u64,
810 pub twaps: Vec<PlatformTwap>,
811}
812
813#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
814#[serde(rename_all = "snake_case")]
815pub enum PlatformTwapControlAction {
816 Place,
817 Cancel,
818}
819
820#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
823#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
824pub enum PlatformTwapChallengeRequest {
825 Place {
826 owner_wallet: String,
827 session_public_key: String,
828 side: PlatformTradeSide,
829 total_size_atoms: String,
830 slices_total: u16,
831 maximum_tolerance_bps: u16,
832 interval_slots: u32,
836 limit_price_atoms: String,
837 },
838 Cancel {
839 owner_wallet: String,
840 session_public_key: String,
841 twap_id: String,
842 },
843}
844
845#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
846#[serde(deny_unknown_fields)]
847pub struct PlatformTwapChallengeResponse {
848 pub schema_version: u16,
849 pub contract_version: String,
850 pub challenge_id: String,
851 pub market_id: String,
852 pub action: PlatformTwapControlAction,
853 pub twap_id: String,
854 pub authorization_payload_base64: String,
855 pub server_time_ms: u64,
856 pub expires_at_ms: u64,
857}
858
859#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
861#[serde(deny_unknown_fields)]
862pub struct PlatformTwapPrepareAuthorization {
863 pub challenge_id: String,
864 pub authorization_signature: String,
866}
867
868#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
872#[serde(untagged)]
873pub enum PlatformTwapPrepareRequest {
874 Authorized(PlatformTwapPrepareAuthorization),
875 Direct(PlatformTwapChallengeRequest),
876}
877
878#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
879#[serde(deny_unknown_fields)]
880pub struct PlatformTwapPrepareResponse {
881 pub schema_version: u16,
882 pub contract_version: String,
883 pub twap_control_id: String,
884 pub market_id: String,
885 pub action: PlatformTwapControlAction,
886 pub twap_id: String,
887 pub transaction_base64: String,
890 pub recent_blockhash: String,
891 pub last_valid_block_height: u64,
892 pub expires_at_ms: u64,
893}
894
895#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
896#[serde(deny_unknown_fields)]
897pub struct PlatformTwapSubmitRequest {
898 pub twap_control_id: String,
899 pub signed_transaction_base64: String,
900 pub idempotency_key: String,
901}
902
903#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
904#[serde(deny_unknown_fields)]
905pub struct PlatformTwapSubmitResponse {
906 pub schema_version: u16,
907 pub contract_version: String,
908 pub twap_control_id: String,
909 pub market_id: String,
910 pub action: PlatformTwapControlAction,
911 pub twap_id: String,
912 pub signature: String,
913 pub status: PlatformOrderSubmissionStatus,
914}
915
916#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
923#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
924#[allow(clippy::large_enum_variant)]
925pub enum PlatformTwapEvent {
926 TwapsSnapshot {
927 schema_version: u16,
928 contract_version: String,
929 market_id: String,
930 wallet_address: String,
931 stream_id: String,
932 sequence: String,
933 server_time_ms: u64,
934 twaps: Vec<PlatformTwap>,
935 },
936 TwapUpdate {
937 schema_version: u16,
938 contract_version: String,
939 market_id: String,
940 wallet_address: String,
941 stream_id: String,
942 sequence: String,
943 previous_sequence: String,
944 server_time_ms: u64,
945 twap: PlatformTwap,
946 },
947 Heartbeat {
948 schema_version: u16,
949 contract_version: String,
950 market_id: String,
951 wallet_address: String,
952 stream_id: String,
953 sequence: String,
954 previous_sequence: String,
955 server_time_ms: u64,
956 },
957}
958
959#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
960pub enum PlatformPortfolioHistoryRange {
961 #[serde(rename = "24h")]
962 Day,
963 #[serde(rename = "7d")]
964 Week,
965 #[serde(rename = "30d")]
966 Month,
967}
968
969#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
970#[serde(deny_unknown_fields)]
971pub struct PlatformPortfolioHistoryPoint {
972 pub recorded_at_ms: u64,
973 pub equity_usd_micros: String,
974 pub available_usd_micros: String,
975 pub locked_usd_micros: String,
976 pub market_count: u32,
977}
978
979#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
982#[serde(deny_unknown_fields)]
983pub struct PlatformPortfolioHistoryResponse {
984 pub schema_version: u16,
985 pub contract_version: String,
986 pub wallet_address: String,
987 pub server_time_ms: u64,
988 pub range: PlatformPortfolioHistoryRange,
989 pub points: Vec<PlatformPortfolioHistoryPoint>,
990 pub collecting: bool,
991 pub first_sample_ms: Option<u64>,
992 pub last_sample_ms: Option<u64>,
993}
994
995#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1000#[serde(deny_unknown_fields)]
1001pub struct PlatformPortfolioBalance {
1002 pub asset_id: String,
1003 pub available_atoms: String,
1005 pub locked_atoms: String,
1007 pub total_atoms: String,
1009 pub value_usd_micros: Option<String>,
1011}
1012
1013#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1016#[serde(deny_unknown_fields)]
1017pub struct PlatformPortfolioPosition {
1018 pub market_id: String,
1019 pub base_asset_id: String,
1020 pub quote_asset_id: String,
1021 pub base_available_atoms: String,
1022 pub base_locked_atoms: String,
1023 pub quote_available_atoms: String,
1024 pub quote_locked_atoms: String,
1025}
1026
1027#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1029#[serde(deny_unknown_fields)]
1030pub struct PlatformPortfolioOrder {
1031 pub market_id: String,
1032 pub order_id: String,
1033 pub side: PlatformTradeSide,
1034 pub order_type: PlatformOrderType,
1035 pub state: PlatformOrderState,
1036 pub limit_price_atoms: String,
1037 pub original_size_atoms: String,
1038 pub remaining_size_atoms: String,
1039}
1040
1041#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1043#[serde(deny_unknown_fields)]
1044pub struct PlatformPortfolioFill {
1045 pub market_id: String,
1046 pub fill_id: String,
1047 pub side: PlatformTradeSide,
1048 pub price_atoms: String,
1049 pub size_atoms: String,
1050 pub fee_quote_atoms: String,
1051 pub fee_is_final: bool,
1052 pub settlement: PlatformSettlementState,
1053 pub executed_at_ms: u64,
1054 pub confirmed_at_ms: Option<u64>,
1055 pub transaction_id: Option<String>,
1056 pub realized_pnl_quote_atoms: String,
1057}
1058
1059#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1066#[serde(deny_unknown_fields)]
1067pub struct PlatformPortfolioResponse {
1068 pub schema_version: u16,
1069 pub contract_version: String,
1070 pub wallet_address: String,
1071 pub server_time_ms: u64,
1072 pub observed_at_ms: u64,
1074 pub observed_slot: String,
1076 pub market_count: u32,
1078 pub balances: Vec<PlatformPortfolioBalance>,
1079 pub positions: Vec<PlatformPortfolioPosition>,
1080 pub open_orders: Vec<PlatformPortfolioOrder>,
1082 pub recent_fills: Vec<PlatformPortfolioFill>,
1084 pub unavailable_market_ids: Vec<String>,
1087 pub equity_usd_micros: Option<String>,
1089 pub available_usd_micros: Option<String>,
1091 pub locked_usd_micros: Option<String>,
1093 pub valuation_complete: bool,
1094 pub unpriced_asset_ids: Vec<String>,
1095}
1096
1097#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1098#[serde(rename_all = "snake_case")]
1099pub enum PlatformVaultState {
1100 Absent,
1101 Active,
1102 Paused,
1103}
1104
1105#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1106#[serde(rename_all = "snake_case")]
1107pub enum PlatformVaultSessionState {
1108 Absent,
1109 Active,
1110 Expired,
1111}
1112
1113#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1114#[serde(rename_all = "snake_case")]
1115pub enum PlatformVaultWithdrawalMode {
1116 Unrestricted,
1117 Blocked,
1118 Restricted,
1119}
1120
1121#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1124#[serde(deny_unknown_fields)]
1125pub struct PlatformVaultSpendingLimit {
1126 pub asset_id: String,
1127 pub maximum_per_execution_atoms: Option<String>,
1128}
1129
1130#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1133#[serde(deny_unknown_fields)]
1134pub struct PlatformVaultSessionStatus {
1135 pub session_public_key: String,
1136 pub state: PlatformVaultSessionState,
1137 pub expires_at_ms: Option<u64>,
1138 pub permanent: bool,
1139 pub minimum_interval_seconds: u32,
1140 pub maximum_tolerance_bps: u16,
1141 pub last_execution_at_ms: Option<u64>,
1142 pub market_execution_ready: bool,
1143 pub price_protection_active: bool,
1144 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1145}
1146
1147#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1148#[serde(deny_unknown_fields)]
1149pub struct PlatformVaultWithdrawalAccess {
1150 pub mode: PlatformVaultWithdrawalMode,
1151 pub allowed_wallet_addresses: Vec<String>,
1152}
1153
1154#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1157#[serde(deny_unknown_fields)]
1158pub struct PlatformVaultStatusResponse {
1159 pub schema_version: u16,
1160 pub contract_version: String,
1161 pub server_time_ms: u64,
1162 pub wallet_address: String,
1163 pub state: PlatformVaultState,
1164 pub session: Option<PlatformVaultSessionStatus>,
1165 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1166}
1167
1168#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1169#[serde(deny_unknown_fields)]
1170pub struct PlatformVaultPausePrepareRequest {
1171 pub wallet_address: String,
1172 pub paused: bool,
1173}
1174
1175#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1178#[serde(deny_unknown_fields)]
1179pub struct PlatformVaultPausePrepareResponse {
1180 pub schema_version: u16,
1181 pub contract_version: String,
1182 pub server_time_ms: u64,
1183 pub wallet_address: String,
1184 pub paused: bool,
1185 pub transaction_base64: String,
1186 pub recent_blockhash: String,
1187 pub owner_signature_required: bool,
1188 pub preparation_id: String,
1192 pub sponsored: bool,
1196 pub submit_by_ms: u64,
1198}
1199
1200#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1201#[serde(rename_all = "snake_case")]
1202pub enum PlatformVaultSetupMode {
1203 Create,
1204 ReplaceSession,
1205}
1206
1207pub const PLATFORM_SESSION_DEFAULT_MINIMUM_INTERVAL_SECONDS: u32 = 0;
1210pub const PLATFORM_SESSION_DEFAULT_MAXIMUM_TOLERANCE_BPS: u16 = 100;
1211pub const PLATFORM_SESSION_MAX_SPENDING_LIMITS: usize = 4;
1213
1214#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1218#[serde(deny_unknown_fields)]
1219pub struct PlatformVaultSetupPrepareRequest {
1220 pub wallet_address: String,
1221 pub session_public_key: String,
1222 #[serde(default)]
1226 pub replace_session_public_key: Option<String>,
1227 #[serde(default)]
1230 pub market_id: Option<String>,
1231 #[serde(default)]
1234 pub expires_at_ms: Option<u64>,
1235 #[serde(default)]
1237 pub minimum_interval_seconds: Option<u32>,
1238 #[serde(default)]
1240 pub maximum_tolerance_bps: Option<u16>,
1241 #[serde(default)]
1244 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1245}
1246
1247#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1250#[serde(deny_unknown_fields)]
1251pub struct PlatformVaultSetupPrepareResponse {
1252 pub schema_version: u16,
1253 pub contract_version: String,
1254 pub server_time_ms: u64,
1255 pub wallet_address: String,
1256 pub session_public_key: String,
1257 pub replace_session_public_key: Option<String>,
1259 pub market_id: Option<String>,
1261 pub mode: PlatformVaultSetupMode,
1262 pub expires_at_ms: Option<u64>,
1263 pub permanent: bool,
1264 pub minimum_interval_seconds: u32,
1266 pub maximum_tolerance_bps: u16,
1267 pub spending_limits: Vec<PlatformVaultSpendingLimit>,
1268 pub transaction_base64: String,
1269 pub recent_blockhash: String,
1270 pub owner_signature_required: bool,
1271 pub preparation_id: String,
1275 pub sponsored: bool,
1279 pub submit_by_ms: u64,
1281}
1282
1283#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1284#[serde(rename_all = "snake_case")]
1285pub enum PlatformVaultDelegateAction {
1286 Revoke,
1287}
1288
1289#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1290#[serde(deny_unknown_fields)]
1291pub struct PlatformVaultDelegatePrepareRequest {
1292 pub wallet_address: String,
1293 pub session_public_key: String,
1294 pub action: PlatformVaultDelegateAction,
1295}
1296
1297#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1300#[serde(deny_unknown_fields)]
1301pub struct PlatformVaultDelegatePrepareResponse {
1302 pub schema_version: u16,
1303 pub contract_version: String,
1304 pub server_time_ms: u64,
1305 pub wallet_address: String,
1306 pub session_public_key: String,
1307 pub action: PlatformVaultDelegateAction,
1308 pub transaction_base64: String,
1309 pub recent_blockhash: String,
1310 pub owner_signature_required: bool,
1311 pub preparation_id: String,
1315 pub sponsored: bool,
1319 pub submit_by_ms: u64,
1321}
1322
1323#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1324#[serde(deny_unknown_fields)]
1325pub struct PlatformVaultPolicyPrepareRequest {
1326 pub wallet_address: String,
1327 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1328}
1329
1330#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1333#[serde(deny_unknown_fields)]
1334pub struct PlatformVaultPolicyPrepareResponse {
1335 pub schema_version: u16,
1336 pub contract_version: String,
1337 pub server_time_ms: u64,
1338 pub wallet_address: String,
1339 pub withdrawal_access: PlatformVaultWithdrawalAccess,
1340 pub transaction_base64: String,
1341 pub recent_blockhash: String,
1342 pub owner_signature_required: bool,
1343 pub preparation_id: String,
1347 pub sponsored: bool,
1351 pub submit_by_ms: u64,
1353}
1354
1355#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1356#[serde(deny_unknown_fields)]
1357pub struct PlatformVaultDepositPrepareRequest {
1358 pub wallet_address: String,
1359 pub market_id: String,
1360 pub asset_id: String,
1361 pub amount_atoms: String,
1362 #[serde(default)]
1367 pub session_public_key: Option<String>,
1368}
1369
1370#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1373#[serde(deny_unknown_fields)]
1374pub struct PlatformVaultDepositPrepareResponse {
1375 pub schema_version: u16,
1376 pub contract_version: String,
1377 pub server_time_ms: u64,
1378 pub wallet_address: String,
1379 pub market_id: String,
1380 pub asset_id: String,
1381 pub amount_atoms: String,
1382 pub network_cost_atoms: String,
1388 pub session_public_key: Option<String>,
1390 pub registers_session: bool,
1394 pub transaction_base64: String,
1395 pub recent_blockhash: String,
1396 pub owner_signature_required: bool,
1397 pub preparation_id: String,
1401 pub sponsored: bool,
1405 pub submit_by_ms: u64,
1407}
1408
1409#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1410#[serde(deny_unknown_fields)]
1411pub struct PlatformVaultWithdrawPrepareRequest {
1412 pub wallet_address: String,
1413 pub market_id: String,
1414 pub asset_id: String,
1415 pub destination_wallet_address: String,
1416 pub amount_atoms: String,
1417}
1418
1419#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1422#[serde(deny_unknown_fields)]
1423pub struct PlatformVaultWithdrawPrepareResponse {
1424 pub schema_version: u16,
1425 pub contract_version: String,
1426 pub server_time_ms: u64,
1427 pub wallet_address: String,
1428 pub market_id: String,
1429 pub asset_id: String,
1430 pub destination_wallet_address: String,
1431 pub amount_atoms: String,
1432 pub transaction_base64: String,
1433 pub recent_blockhash: String,
1434 pub owner_signature_required: bool,
1435 pub preparation_id: String,
1439 pub sponsored: bool,
1443 pub submit_by_ms: u64,
1445}
1446
1447#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1449#[serde(rename_all = "snake_case")]
1450pub enum PlatformVaultAction {
1451 Setup,
1452 Deposit,
1453 Withdraw,
1454 Delegate,
1455 Policy,
1456 Pause,
1457}
1458
1459#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1460#[serde(rename_all = "snake_case")]
1461pub enum PlatformVaultSubmissionStatus {
1462 Submitted,
1464 Confirmed,
1465 Failed,
1466}
1467
1468#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1473#[serde(deny_unknown_fields)]
1474pub struct PlatformVaultSubmitRequest {
1475 pub preparation_id: String,
1476 pub signed_transaction_base64: String,
1477 pub idempotency_key: String,
1478}
1479
1480#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1482#[serde(deny_unknown_fields)]
1483pub struct PlatformVaultSubmitResponse {
1484 pub schema_version: u16,
1485 pub contract_version: String,
1486 pub preparation_id: String,
1487 pub action: PlatformVaultAction,
1488 pub wallet_address: String,
1489 pub sponsored: bool,
1490 pub signature: String,
1491 pub status: PlatformVaultSubmissionStatus,
1492 pub failure_code: Option<String>,
1494 pub updated_at_ms: u64,
1495}
1496
1497#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1498#[serde(deny_unknown_fields)]
1499pub struct PlatformRewardStanding {
1500 pub rank: u32,
1501 pub wallet_address: String,
1502 pub points: String,
1503}
1504
1505#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1506#[serde(deny_unknown_fields)]
1507pub struct PlatformOwnerRewards {
1508 pub wallet_address: String,
1509 pub rank: Option<u32>,
1510 pub points: String,
1511 pub trading_points: String,
1512 pub making_points: String,
1513 pub bug_points: String,
1514 pub referral_points: String,
1515}
1516
1517#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1518#[serde(deny_unknown_fields)]
1519pub struct PlatformRewardsResponse {
1520 pub schema_version: u16,
1521 pub contract_version: String,
1522 pub server_time_ms: u64,
1523 pub season: String,
1524 pub total_wallets: u32,
1525 pub owner: Option<PlatformOwnerRewards>,
1526 pub standings: Vec<PlatformRewardStanding>,
1527}
1528
1529#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1530#[serde(deny_unknown_fields)]
1531pub struct PlatformReferralsResponse {
1532 pub schema_version: u16,
1533 pub contract_version: String,
1534 pub server_time_ms: u64,
1535 pub wallet_address: String,
1536 pub enabled: bool,
1537 pub cash_rewards_enabled: bool,
1538 pub referral_code: Option<String>,
1539 pub referred_wallets: u32,
1540 pub referral_points: String,
1541 pub referred_by: Option<String>,
1542 pub referral_locked: bool,
1543 pub cash_accrued_atoms: String,
1544 pub cash_paid_atoms: String,
1545 pub cash_claimable_atoms: String,
1546}
1547
1548#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1549#[serde(deny_unknown_fields)]
1550pub struct PlatformReferralLinkRequest {
1551 pub wallet_address: String,
1552 pub referral_code: String,
1553 pub authorization_signature: String,
1554}
1555
1556#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1557#[serde(deny_unknown_fields)]
1558pub struct PlatformReferralLinkResponse {
1559 pub schema_version: u16,
1560 pub contract_version: String,
1561 pub server_time_ms: u64,
1562 pub wallet_address: String,
1563 pub referral_code: String,
1564 pub status: String,
1565}
1566
1567#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1568#[serde(deny_unknown_fields)]
1569pub struct PlatformReferralClaimRequest {
1570 pub wallet_address: String,
1571 pub payout_wallet_address: Option<String>,
1572 pub authorization_signature: String,
1573}
1574
1575#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1576#[serde(deny_unknown_fields)]
1577pub struct PlatformReferralClaimResponse {
1578 pub schema_version: u16,
1579 pub contract_version: String,
1580 pub server_time_ms: u64,
1581 pub wallet_address: String,
1582 pub payout_wallet_address: String,
1583 pub claimable_atoms: String,
1584 pub status: String,
1585}
1586
1587#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1588#[serde(rename_all = "snake_case")]
1589pub enum PlatformBugStatus {
1590 Pending,
1591 Confirmed,
1592 Rejected,
1593}
1594
1595#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1596#[serde(deny_unknown_fields)]
1597pub struct PlatformBugReport {
1598 pub bug_id: String,
1599 pub status: PlatformBugStatus,
1600 pub severity: u8,
1601 pub points: String,
1602 pub created_at_ms: u64,
1603 pub triaged_at_ms: Option<u64>,
1604 pub completed_at_ms: Option<u64>,
1605}
1606
1607#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1608#[serde(deny_unknown_fields)]
1609pub struct PlatformBugsResponse {
1610 pub schema_version: u16,
1611 pub contract_version: String,
1612 pub server_time_ms: u64,
1613 pub wallet_address: String,
1614 pub points: String,
1615 pub confirmed_reports: u32,
1616 pub reports: Vec<PlatformBugReport>,
1617}
1618
1619#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1620#[serde(deny_unknown_fields)]
1621pub struct PlatformBugSubmitRequest {
1622 pub owner_wallet: String,
1623 pub message: String,
1624 pub authorization_signature: String,
1627}
1628
1629#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1630#[serde(deny_unknown_fields)]
1631pub struct PlatformBugSubmitResponse {
1632 pub schema_version: u16,
1633 pub contract_version: String,
1634 pub server_time_ms: u64,
1635 pub bug_id: String,
1636 pub status: PlatformBugStatus,
1637}
1638
1639#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1640#[serde(rename_all = "snake_case")]
1641pub enum PlatformTradeSide {
1642 Buy,
1643 Sell,
1644}
1645
1646#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1647#[serde(deny_unknown_fields)]
1648pub struct PlatformTrade {
1649 pub trade_id: String,
1650 pub side: PlatformTradeSide,
1651 pub price_atoms: String,
1652 pub size_atoms: String,
1653 pub executed_at_ms: u64,
1654}
1655
1656#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1657#[serde(deny_unknown_fields)]
1658pub struct PlatformTradesResponse {
1659 pub schema_version: u16,
1660 pub contract_version: String,
1661 pub market_id: String,
1662 pub server_time_ms: u64,
1663 pub trades: Vec<PlatformTrade>,
1664}
1665
1666#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1667#[serde(rename_all = "snake_case")]
1668pub enum PlatformOrderType {
1669 GoodUntilCancelled,
1670 ImmediateOrCancel,
1671 FillOrKill,
1672 PostOnly,
1673}
1674
1675#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1679#[serde(rename_all = "snake_case")]
1680pub enum PlatformOrderAction {
1681 Place,
1682 Cancel,
1683 CancelAll,
1684 Replace,
1687 Batch,
1690}
1691
1692#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1695#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
1696pub enum PlatformOrderBatchOperation {
1697 Place {
1698 #[serde(default, skip_serializing_if = "Option::is_none")]
1704 account_sequence: Option<String>,
1705 client_order_id: String,
1706 side: PlatformTradeSide,
1707 order_type: PlatformOrderType,
1708 limit_price_atoms: String,
1709 size_atoms: String,
1710 },
1711 Cancel {
1712 order_id: String,
1713 },
1714 Replace {
1715 order_id: String,
1716 #[serde(default, skip_serializing_if = "Option::is_none")]
1717 account_sequence: Option<String>,
1718 client_order_id: String,
1719 side: PlatformTradeSide,
1720 order_type: PlatformOrderType,
1721 limit_price_atoms: String,
1722 size_atoms: String,
1723 },
1724}
1725
1726#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1730#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
1731pub enum PlatformOrderChallengeRequest {
1732 Place {
1733 owner_wallet: String,
1734 session_public_key: String,
1735 #[serde(default, skip_serializing_if = "Option::is_none")]
1739 account_sequence: Option<String>,
1740 client_order_id: String,
1741 side: PlatformTradeSide,
1742 order_type: PlatformOrderType,
1743 limit_price_atoms: String,
1744 size_atoms: String,
1745 },
1746 Cancel {
1747 owner_wallet: String,
1748 session_public_key: String,
1749 order_id: String,
1750 },
1751 CancelAll {
1752 owner_wallet: String,
1753 session_public_key: String,
1754 },
1755 Replace {
1756 owner_wallet: String,
1757 session_public_key: String,
1758 order_id: String,
1759 #[serde(default, skip_serializing_if = "Option::is_none")]
1760 account_sequence: Option<String>,
1761 client_order_id: String,
1762 side: PlatformTradeSide,
1763 order_type: PlatformOrderType,
1764 limit_price_atoms: String,
1765 size_atoms: String,
1766 },
1767 Batch {
1768 owner_wallet: String,
1769 session_public_key: String,
1770 operations: Vec<PlatformOrderBatchOperation>,
1771 },
1772}
1773
1774#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1775#[serde(deny_unknown_fields)]
1776pub struct PlatformOrderChallengeResponse {
1777 pub schema_version: u16,
1778 pub contract_version: String,
1779 pub challenge_id: String,
1780 pub market_id: String,
1781 pub action: PlatformOrderAction,
1782 pub order_ids: Vec<String>,
1786 pub authorization_payload_base64: String,
1787 pub server_time_ms: u64,
1788 pub expires_at_ms: u64,
1789}
1790
1791#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1793#[serde(deny_unknown_fields)]
1794pub struct PlatformOrderPrepareAuthorization {
1795 pub challenge_id: String,
1796 #[serde(default, skip_serializing_if = "Option::is_none")]
1801 pub authorization_signature: Option<String>,
1802}
1803
1804#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1810#[serde(untagged)]
1811pub enum PlatformOrderPrepareRequest {
1812 Authorized(PlatformOrderPrepareAuthorization),
1813 Direct(PlatformOrderChallengeRequest),
1814}
1815
1816#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1817#[serde(deny_unknown_fields)]
1818pub struct PlatformOrderPrepareResponse {
1819 pub schema_version: u16,
1820 pub contract_version: String,
1821 pub order_control_id: String,
1822 pub market_id: String,
1823 pub action: PlatformOrderAction,
1824 pub order_ids: Vec<String>,
1825 pub transaction_base64: String,
1828 pub recent_blockhash: String,
1829 pub last_valid_block_height: u64,
1830 pub expires_at_ms: u64,
1831}
1832
1833#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1834#[serde(deny_unknown_fields)]
1835pub struct PlatformOrderSubmitRequest {
1836 pub order_control_id: String,
1837 pub signed_transaction_base64: String,
1838 pub idempotency_key: String,
1839}
1840
1841#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1842#[serde(rename_all = "snake_case")]
1843pub enum PlatformOrderSubmissionStatus {
1844 Submitted,
1845}
1846
1847#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1848#[serde(deny_unknown_fields)]
1849pub struct PlatformOrderSubmitResponse {
1850 pub schema_version: u16,
1851 pub contract_version: String,
1852 pub order_control_id: String,
1853 pub market_id: String,
1854 pub action: PlatformOrderAction,
1855 pub order_ids: Vec<String>,
1856 pub signature: String,
1857 pub status: PlatformOrderSubmissionStatus,
1858}
1859
1860#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1861#[serde(deny_unknown_fields)]
1862pub struct PlatformOrderStatusRequest {
1863 pub order_control_id: String,
1864 pub idempotency_key: String,
1865}
1866
1867#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1868#[serde(rename_all = "snake_case")]
1869pub enum PlatformOrderControlStatus {
1870 Submitting,
1871 Submitted,
1872 Failed,
1873}
1874
1875#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1876#[serde(deny_unknown_fields)]
1877pub struct PlatformOrderStatusResponse {
1878 pub schema_version: u16,
1879 pub contract_version: String,
1880 pub order_control_id: String,
1881 pub market_id: String,
1882 pub action: PlatformOrderAction,
1883 pub order_ids: Vec<String>,
1884 pub signature: String,
1885 pub status: PlatformOrderControlStatus,
1886 pub failure_code: Option<String>,
1887 pub updated_at_ms: u64,
1888}
1889
1890#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
1895#[serde(rename_all = "snake_case")]
1896pub enum PlatformSelfTradePrevention {
1897 #[default]
1898 None,
1899 CancelTaker,
1900 CancelMaker,
1901 CancelBoth,
1902 SkipOwnLiquidity,
1903}
1904
1905#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1909#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1910pub enum PlatformOrderCommand {
1911 Probe {
1913 nonce: String,
1914 },
1915 Challenge {
1916 request: PlatformOrderChallengeRequest,
1917 #[serde(default)]
1918 self_trade_prevention: PlatformSelfTradePrevention,
1919 },
1920 Prepare {
1921 request: PlatformOrderPrepareRequest,
1922 },
1923 Submit {
1924 request: PlatformOrderSubmitRequest,
1925 },
1926 Status {
1927 request: PlatformOrderStatusRequest,
1928 },
1929 DeadManArm {
1930 timeout_ms: u64,
1931 request: PlatformOrderSubmitRequest,
1932 },
1933 DeadManStatus,
1934 DeadManHeartbeat,
1935 DeadManDisarm,
1936}
1937
1938#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1945#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1946pub enum PlatformOrderCommandClientFrame {
1947 Authenticate {
1948 owner_wallet: String,
1949 session_public_key: String,
1950 signature: String,
1952 #[serde(default, skip_serializing_if = "Option::is_none")]
1955 batch_format: Option<PlatformOrderCommandBatchFormat>,
1956 },
1957 Command {
1958 request_id: String,
1959 sequence: String,
1960 command: PlatformOrderCommand,
1961 },
1962}
1963
1964#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
1965#[serde(rename_all = "snake_case")]
1966pub enum PlatformOrderCommandBatchFormat {
1967 CompactV1,
1968}
1969
1970#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
1974#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
1975pub enum PlatformOrderCommandBatchEvent {
1976 ProbeResult {
1977 request_id: String,
1978 nonce: String,
1979 },
1980 ChallengeResult {
1981 request_id: String,
1982 self_trade_prevention: PlatformSelfTradePrevention,
1983 prevented_order_ids: Vec<String>,
1984 effective_request: PlatformOrderChallengeRequest,
1985 response: PlatformOrderChallengeResponse,
1986 },
1987 PrepareResult {
1988 request_id: String,
1989 response: PlatformOrderPrepareResponse,
1990 },
1991 SubmitResult {
1992 request_id: String,
1993 response: PlatformOrderSubmitResponse,
1994 },
1995 StatusResult {
1996 request_id: String,
1997 response: PlatformOrderStatusResponse,
1998 },
1999 DeadManResult {
2000 request_id: String,
2001 state: PlatformDeadManState,
2002 },
2003 CommandError {
2004 request_id: String,
2005 error: PublicOperationError,
2006 },
2007 Heartbeat,
2008}
2009
2010#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2011#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2012pub enum PlatformOrderCommandServerFrame {
2013 EventBatch {
2014 schema_version: u16,
2015 contract_version: String,
2016 market_id: String,
2017 stream_id: String,
2018 first_sequence: String,
2019 previous_sequence: String,
2020 server_time_ms: u64,
2021 events: Vec<PlatformOrderCommandBatchEvent>,
2022 },
2023}
2024
2025#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2026#[serde(rename_all = "snake_case")]
2027pub enum PlatformDeadManStatus {
2028 Armed,
2029 Triggering,
2030 Triggered,
2031 Disarmed,
2032 Expired,
2033 Failed,
2034}
2035
2036#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2037#[serde(deny_unknown_fields)]
2038pub struct PlatformDeadManState {
2039 pub status: PlatformDeadManStatus,
2040 pub timeout_ms: u64,
2041 pub heartbeat_deadline_ms: u64,
2042 pub order_control_id: Option<String>,
2043 pub signature: Option<String>,
2044 pub failure_code: Option<String>,
2045 pub updated_at_ms: u64,
2046}
2047
2048#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2054#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2055pub enum PlatformOrderCommandEvent {
2056 AuthChallenge {
2057 schema_version: u16,
2058 contract_version: String,
2059 market_id: String,
2060 challenge: String,
2061 server_time_ms: u64,
2062 expires_at_ms: u64,
2063 },
2064 Ready {
2065 schema_version: u16,
2066 contract_version: String,
2067 market_id: String,
2068 stream_id: String,
2069 sequence: String,
2070 server_time_ms: u64,
2071 },
2072 ProbeResult {
2073 schema_version: u16,
2074 contract_version: String,
2075 market_id: String,
2076 stream_id: String,
2077 sequence: String,
2078 previous_sequence: String,
2079 request_id: String,
2080 nonce: String,
2081 server_time_ms: u64,
2082 },
2083 ChallengeResult {
2084 schema_version: u16,
2085 contract_version: String,
2086 market_id: String,
2087 stream_id: String,
2088 sequence: String,
2089 previous_sequence: String,
2090 request_id: String,
2091 self_trade_prevention: PlatformSelfTradePrevention,
2092 prevented_order_ids: Vec<String>,
2093 effective_request: PlatformOrderChallengeRequest,
2094 response: PlatformOrderChallengeResponse,
2095 server_time_ms: u64,
2096 },
2097 PrepareResult {
2098 schema_version: u16,
2099 contract_version: String,
2100 market_id: String,
2101 stream_id: String,
2102 sequence: String,
2103 previous_sequence: String,
2104 request_id: String,
2105 response: PlatformOrderPrepareResponse,
2106 server_time_ms: u64,
2107 },
2108 SubmitResult {
2109 schema_version: u16,
2110 contract_version: String,
2111 market_id: String,
2112 stream_id: String,
2113 sequence: String,
2114 previous_sequence: String,
2115 request_id: String,
2116 response: PlatformOrderSubmitResponse,
2117 server_time_ms: u64,
2118 },
2119 StatusResult {
2120 schema_version: u16,
2121 contract_version: String,
2122 market_id: String,
2123 stream_id: String,
2124 sequence: String,
2125 previous_sequence: String,
2126 request_id: String,
2127 response: PlatformOrderStatusResponse,
2128 server_time_ms: u64,
2129 },
2130 DeadManResult {
2131 schema_version: u16,
2132 contract_version: String,
2133 market_id: String,
2134 stream_id: String,
2135 sequence: String,
2136 previous_sequence: String,
2137 request_id: String,
2138 state: PlatformDeadManState,
2139 server_time_ms: u64,
2140 },
2141 CommandError {
2142 schema_version: u16,
2143 contract_version: String,
2144 market_id: String,
2145 stream_id: String,
2146 sequence: String,
2147 previous_sequence: String,
2148 request_id: String,
2149 error: PublicOperationError,
2150 server_time_ms: u64,
2151 },
2152 Heartbeat {
2153 schema_version: u16,
2154 contract_version: String,
2155 market_id: String,
2156 stream_id: String,
2157 sequence: String,
2158 previous_sequence: String,
2159 server_time_ms: u64,
2160 },
2161}
2162
2163#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2164#[serde(deny_unknown_fields)]
2165pub struct PlatformAccountOrder {
2166 pub order_id: String,
2167 pub side: PlatformTradeSide,
2168 pub order_type: PlatformOrderType,
2169 pub state: PlatformOrderState,
2170 pub limit_price_atoms: String,
2171 pub original_size_atoms: String,
2172 pub remaining_size_atoms: String,
2173}
2174
2175#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2176#[serde(deny_unknown_fields)]
2177pub struct PlatformAccountFill {
2178 pub fill_id: String,
2179 pub side: PlatformTradeSide,
2180 pub price_atoms: String,
2181 pub size_atoms: String,
2182 pub fee_quote_atoms: String,
2183 pub fee_is_final: bool,
2184 pub settlement: PlatformSettlementState,
2185 pub executed_at_ms: u64,
2186 pub confirmed_at_ms: Option<u64>,
2187 pub transaction_id: Option<String>,
2188 pub realized_pnl_quote_atoms: String,
2189}
2190
2191#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2192#[serde(deny_unknown_fields)]
2193pub struct PlatformAccountSnapshotResponse {
2194 pub schema_version: u16,
2195 pub contract_version: String,
2196 pub market_id: String,
2197 pub wallet_address: String,
2198 pub server_time_ms: u64,
2199 pub orders: Vec<PlatformAccountOrder>,
2200 pub fills: Vec<PlatformAccountFill>,
2201}
2202
2203#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2204#[serde(rename_all = "snake_case")]
2205pub enum PlatformMakerReputationTier {
2206 Probation,
2207 Bronze,
2208 Silver,
2209 Gold,
2210 Platinum,
2211}
2212
2213#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2214#[serde(deny_unknown_fields)]
2215pub struct PlatformMakerTierProgress {
2216 pub next_tier: Option<PlatformMakerReputationTier>,
2217 pub reputation_score_required: Option<u16>,
2218 pub reputation_score_remaining: u16,
2219 pub quote_requests_required: Option<String>,
2220 pub quote_requests_remaining: String,
2221 pub stake_atoms_required: Option<String>,
2222 pub stake_atoms_remaining: String,
2223 pub tenure_slots_required: Option<String>,
2224 pub tenure_slots_remaining: String,
2225}
2226
2227#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2231#[serde(deny_unknown_fields)]
2232pub struct PlatformMakerReputationResponse {
2233 pub schema_version: u16,
2234 pub contract_version: String,
2235 pub market_id: String,
2236 pub maker_id: String,
2237 pub wallet_address: String,
2238 pub active: bool,
2239 pub tier: PlatformMakerReputationTier,
2240 pub reputation_score: u16,
2241 pub total_quote_requests: String,
2242 pub successful_fills: String,
2243 pub missed_quote_requests: String,
2244 pub fill_rate_bps: u16,
2245 pub consecutive_misses: u16,
2246 pub lifetime_filled_quote_atoms: String,
2247 pub distinct_counterparties: u16,
2248 pub recent_average_latency_ms: u16,
2249 pub configured_minimum_spread_bps: u16,
2250 pub weighted_average_spread_bps: u16,
2251 pub stake_atoms: String,
2252 pub epoch_start_stake_atoms: String,
2253 pub epoch_slashed_atoms: String,
2254 pub epoch_slashed_bps: u16,
2255 pub lifetime_auto_slashed_atoms: String,
2256 pub registered_slot: String,
2257 pub last_active_slot: String,
2258 pub last_settled_slot: String,
2259 pub revoked_at_slot: Option<String>,
2260 pub tenure_slots: String,
2261 pub signed_quote_stream_eligible: bool,
2262 pub minimum_quote_interval_ms: Option<u16>,
2263 pub tier_progress: PlatformMakerTierProgress,
2264 pub server_time_ms: u64,
2265}
2266
2267#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2268#[serde(rename_all = "snake_case")]
2269pub enum PlatformMakerSide {
2270 Buy,
2271 Sell,
2272}
2273
2274#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2275#[serde(rename_all = "snake_case")]
2276pub enum PlatformOracleHealth {
2277 Fresh,
2278 Stale,
2279 Unknown,
2280}
2281
2282#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2284#[serde(deny_unknown_fields)]
2285pub struct PlatformMakerFirmOrderSummary {
2286 pub resting_orders: u32,
2287 pub bid_orders: u32,
2288 pub ask_orders: u32,
2289 pub bid_size_atoms: String,
2290 pub ask_size_atoms: String,
2291}
2292
2293#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2295#[serde(deny_unknown_fields)]
2296pub struct PlatformMakerSignedQuote {
2297 pub side: PlatformMakerSide,
2298 pub price_atoms: String,
2299 pub size_atoms: String,
2300 pub nonce: String,
2301 pub issued_at_ms: u64,
2302 pub expires_at_ms: u64,
2303}
2304
2305#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2307#[serde(deny_unknown_fields)]
2308pub struct PlatformMakerIntentStatus {
2309 pub active: bool,
2310 pub side: PlatformMakerIntentSide,
2311 pub minimum_price_atoms: String,
2312 pub maximum_price_atoms: String,
2313 pub maximum_fill_size_atoms: String,
2314 pub remaining_fill_size_atoms: String,
2316 pub minimum_spread_bps: u16,
2317 pub stake_atoms: String,
2318}
2319
2320#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2322#[serde(deny_unknown_fields)]
2323pub struct PlatformMakerSignedQuoteLane {
2324 pub eligible: bool,
2325 pub live_quotes: Vec<PlatformMakerSignedQuote>,
2326}
2327
2328#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2329#[serde(deny_unknown_fields)]
2330pub struct PlatformMakerStrandLevel {
2331 pub price_atoms: Option<String>,
2333 pub size_atoms: String,
2334 pub remaining_size_atoms: String,
2335}
2336
2337#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2339#[serde(deny_unknown_fields)]
2340pub struct PlatformMakerStrandStatus {
2341 pub enabled: bool,
2342 pub async_only: bool,
2343 pub expired: bool,
2345 pub mid_price_atoms: String,
2346 pub tick_size_atoms: String,
2347 pub valid_until_slot: Option<String>,
2349 pub bids: Vec<PlatformMakerStrandLevel>,
2350 pub asks: Vec<PlatformMakerStrandLevel>,
2351 pub maximum_exposure_atoms: String,
2352 pub remaining_exposure_atoms: String,
2353}
2354
2355#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2357#[serde(deny_unknown_fields)]
2358pub struct PlatformMakerCurrentStatus {
2359 pub enabled: bool,
2360 pub async_only: bool,
2361 pub expired: bool,
2362 pub half_spread_bps: u16,
2363 pub band_step_bps: u16,
2364 pub maximum_confidence_bps: u16,
2365 pub maximum_oracle_age_seconds: u32,
2366 pub sync_spread_bps: u16,
2367 pub valid_until_slot: Option<String>,
2369 pub bid_depth_atoms: Vec<String>,
2370 pub ask_depth_atoms: Vec<String>,
2371 pub maximum_exposure_atoms: String,
2372 pub remaining_exposure_atoms: String,
2373 pub oracle_health: PlatformOracleHealth,
2375}
2376
2377#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2379#[serde(deny_unknown_fields)]
2380pub struct PlatformMakerDeadManGuard {
2381 pub session_public_key: String,
2382 pub status: PlatformDeadManStatus,
2383 pub timeout_ms: u64,
2384 pub heartbeat_deadline_ms: u64,
2385 pub updated_at_ms: u64,
2386}
2387
2388#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2393#[serde(deny_unknown_fields)]
2394pub struct PlatformMakerStatusResponse {
2395 pub schema_version: u16,
2396 pub contract_version: String,
2397 pub market_id: String,
2398 pub maker_id: String,
2399 pub wallet_address: String,
2400 pub server_time_ms: u64,
2401 pub current_slot: String,
2402 pub firm_orders: PlatformMakerFirmOrderSummary,
2403 pub intent: Option<PlatformMakerIntentStatus>,
2404 pub signed_quotes: PlatformMakerSignedQuoteLane,
2405 pub strands: Vec<PlatformMakerStrandStatus>,
2406 pub currents: Vec<PlatformMakerCurrentStatus>,
2407 pub dead_man_guards: Vec<PlatformMakerDeadManGuard>,
2408 pub active_products: u16,
2411}
2412
2413#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2416#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
2417pub enum PlatformMakerStrandPrepareRequest {
2418 Upsert {
2419 maker_wallet: String,
2420 enabled: bool,
2421 async_only: bool,
2422 sync_spread_ticks: u16,
2423 mid_price_atoms: String,
2424 #[serde(alias = "max_exposure_base_lots")]
2425 max_exposure_base_atoms: String,
2426 bid_offsets_ticks: Vec<u16>,
2427 ask_offsets_ticks: Vec<u16>,
2428 #[serde(alias = "bid_sizes_base_lots")]
2429 bid_sizes_base_atoms: Vec<String>,
2430 #[serde(alias = "ask_sizes_base_lots")]
2431 ask_sizes_base_atoms: Vec<String>,
2432 valid_until_slot: String,
2433 },
2434 Recenter {
2435 maker_wallet: String,
2436 new_mid_price_atoms: String,
2437 valid_until_slot: String,
2438 },
2439 SetEnabled {
2440 maker_wallet: String,
2441 enabled: bool,
2442 },
2443 Cancel {
2444 maker_wallet: String,
2445 },
2446}
2447
2448#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2451#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
2452pub enum PlatformMakerCurrentPrepareRequest {
2453 Upsert {
2454 maker_wallet: String,
2455 enabled: bool,
2456 async_only: bool,
2457 half_spread_bps: u16,
2458 band_step_bps: u16,
2459 max_conf_bps: u16,
2460 max_oracle_dev_bps: u16,
2461 max_oracle_age_secs: u32,
2462 sync_spread_bps: u16,
2463 max_exposure_base_atoms: String,
2464 bid_depth_base_atoms: Vec<String>,
2465 ask_depth_base_atoms: Vec<String>,
2466 valid_until_slot: String,
2467 },
2468 Cancel {
2469 maker_wallet: String,
2470 },
2471}
2472
2473#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2474#[serde(rename_all = "snake_case")]
2475pub enum PlatformMakerControlProduct {
2476 Strand,
2477 Current,
2478}
2479
2480#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2481#[serde(rename_all = "snake_case")]
2482pub enum PlatformMakerControlAction {
2483 StrandUpsert,
2484 StrandRecenter,
2485 StrandSetEnabled,
2486 StrandCancel,
2487 CurrentUpsert,
2488 CurrentCancel,
2489}
2490
2491#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2492#[serde(deny_unknown_fields)]
2493pub struct PlatformMakerControlPrepareResponse {
2494 pub schema_version: u16,
2495 pub contract_version: String,
2496 pub maker_control_id: String,
2497 pub market_id: String,
2498 pub maker_wallet: String,
2499 pub product: PlatformMakerControlProduct,
2500 pub action: PlatformMakerControlAction,
2501 pub transaction_base64: String,
2505 pub recent_blockhash: String,
2506 pub last_valid_block_height: u64,
2507 pub expires_at_ms: u64,
2508}
2509
2510#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2511#[serde(deny_unknown_fields)]
2512pub struct PlatformMakerControlSubmitRequest {
2513 pub maker_control_id: String,
2514 pub signed_transaction_base64: String,
2515 pub idempotency_key: String,
2516}
2517
2518#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2519#[serde(rename_all = "snake_case")]
2520pub enum PlatformMakerControlSubmissionStatus {
2521 Submitted,
2522}
2523
2524#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2525#[serde(deny_unknown_fields)]
2526pub struct PlatformMakerControlSubmitResponse {
2527 pub schema_version: u16,
2528 pub contract_version: String,
2529 pub maker_control_id: String,
2530 pub market_id: String,
2531 pub maker_wallet: String,
2532 pub product: PlatformMakerControlProduct,
2533 pub action: PlatformMakerControlAction,
2534 pub signature: String,
2535 pub status: PlatformMakerControlSubmissionStatus,
2536}
2537
2538#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2541#[serde(rename_all = "snake_case")]
2542pub enum PlatformMakerIntentSide {
2543 Buy,
2544 Sell,
2545 Both,
2546}
2547
2548#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2552#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)]
2553pub enum PlatformMakerIntentPrepareRequest {
2554 Post {
2555 market_id: String,
2556 owner_wallet: String,
2557 session_public_key: String,
2558 side: PlatformMakerIntentSide,
2559 min_price_atoms: String,
2560 max_price_atoms: String,
2561 max_fill_size_atoms: String,
2562 },
2563 Revoke {
2564 market_id: String,
2565 owner_wallet: String,
2566 session_public_key: String,
2567 },
2568}
2569
2570#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2571#[serde(rename_all = "snake_case")]
2572pub enum PlatformMakerIntentAction {
2573 Post,
2574 Revoke,
2575}
2576
2577#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2581#[serde(deny_unknown_fields)]
2582pub struct PlatformMakerIntentPrepareResponse {
2583 pub schema_version: u16,
2584 pub contract_version: String,
2585 pub market_id: String,
2586 pub owner_wallet: String,
2587 pub vault_address: String,
2588 pub session_public_key: String,
2589 pub intent_address: String,
2590 pub action: PlatformMakerIntentAction,
2591 pub transaction_base64: String,
2592 pub recent_blockhash: String,
2593 pub last_valid_block_height: u64,
2594 pub expires_at_ms: u64,
2595 pub sponsored: bool,
2598}
2599
2600#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2601#[serde(deny_unknown_fields)]
2602pub struct PlatformMakerIntentSubmitRequest {
2603 pub signed_transaction_base64: String,
2604}
2605
2606#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2607#[serde(deny_unknown_fields)]
2608pub struct PlatformMakerIntentSubmitResponse {
2609 pub signature: String,
2610}
2611
2612#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
2614#[serde(rename_all = "snake_case")]
2615pub enum PlatformMakerProduct {
2616 FirmOrder,
2617 Intent,
2618 Strand,
2619 Current,
2620}
2621
2622#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2625#[serde(deny_unknown_fields)]
2626pub struct PlatformMakerFill {
2627 pub fill_id: String,
2628 pub product: PlatformMakerProduct,
2629 pub side: PlatformTradeSide,
2630 pub price_atoms: String,
2631 pub size_atoms: String,
2632 pub fee_quote_atoms: String,
2633 pub fee_is_final: bool,
2634 pub settlement: PlatformSettlementState,
2635 pub executed_at_ms: u64,
2636 pub confirmed_at_ms: Option<u64>,
2637 pub transaction_id: Option<String>,
2638 pub realized_pnl_quote_atoms: String,
2639}
2640
2641#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2647#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2648pub enum PlatformMakerEvent {
2649 AuthChallenge {
2650 schema_version: u16,
2651 contract_version: String,
2652 market_id: String,
2653 wallet_address: String,
2654 challenge: String,
2655 server_time_ms: u64,
2656 expires_at_ms: u64,
2657 },
2658 MakerSnapshot {
2659 schema_version: u16,
2660 contract_version: String,
2661 market_id: String,
2662 wallet_address: String,
2663 stream_id: String,
2664 sequence: String,
2665 server_time_ms: u64,
2666 status: PlatformMakerStatusResponse,
2667 fills: Vec<PlatformMakerFill>,
2668 },
2669 MakerFill {
2670 schema_version: u16,
2671 contract_version: String,
2672 market_id: String,
2673 wallet_address: String,
2674 stream_id: String,
2675 sequence: String,
2676 previous_sequence: String,
2677 server_time_ms: u64,
2678 fill: PlatformMakerFill,
2679 },
2680 MakerStatus {
2681 schema_version: u16,
2682 contract_version: String,
2683 market_id: String,
2684 wallet_address: String,
2685 stream_id: String,
2686 sequence: String,
2687 previous_sequence: String,
2688 server_time_ms: u64,
2689 status: PlatformMakerStatusResponse,
2690 },
2691 Heartbeat {
2692 schema_version: u16,
2693 contract_version: String,
2694 market_id: String,
2695 wallet_address: String,
2696 stream_id: String,
2697 sequence: String,
2698 previous_sequence: String,
2699 server_time_ms: u64,
2700 },
2701}
2702
2703#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2704#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2705pub enum PlatformAccountEvent {
2706 AuthChallenge {
2707 schema_version: u16,
2708 contract_version: String,
2709 market_id: String,
2710 wallet_address: String,
2711 challenge: String,
2712 server_time_ms: u64,
2713 expires_at_ms: u64,
2714 },
2715 AccountSnapshot {
2716 schema_version: u16,
2717 contract_version: String,
2718 market_id: String,
2719 wallet_address: String,
2720 stream_id: String,
2721 sequence: String,
2722 server_time_ms: u64,
2723 orders: Vec<PlatformAccountOrder>,
2724 fills: Vec<PlatformAccountFill>,
2725 },
2726 OrdersSnapshot {
2727 schema_version: u16,
2728 contract_version: String,
2729 market_id: String,
2730 wallet_address: String,
2731 stream_id: String,
2732 sequence: String,
2733 previous_sequence: String,
2734 server_time_ms: u64,
2735 orders: Vec<PlatformAccountOrder>,
2736 },
2737 Fill {
2738 schema_version: u16,
2739 contract_version: String,
2740 market_id: String,
2741 wallet_address: String,
2742 stream_id: String,
2743 sequence: String,
2744 previous_sequence: String,
2745 server_time_ms: u64,
2746 fill: PlatformAccountFill,
2747 },
2748 Heartbeat {
2749 schema_version: u16,
2750 contract_version: String,
2751 market_id: String,
2752 wallet_address: String,
2753 stream_id: String,
2754 sequence: String,
2755 previous_sequence: String,
2756 server_time_ms: u64,
2757 },
2758}
2759
2760#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2761#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
2762pub enum PlatformMarketDataEvent {
2763 BookSnapshot {
2764 schema_version: u16,
2765 contract_version: String,
2766 market_id: String,
2767 stream_id: String,
2768 sequence: String,
2769 server_time_ms: u64,
2770 snapshot_id: String,
2771 bids: Vec<PlatformBookLevel>,
2772 asks: Vec<PlatformBookLevel>,
2773 },
2774 BookDelta {
2775 schema_version: u16,
2776 contract_version: String,
2777 market_id: String,
2778 stream_id: String,
2779 sequence: String,
2780 previous_sequence: String,
2781 server_time_ms: u64,
2782 changes: Vec<PlatformBookChange>,
2783 },
2784 BestBidAsk {
2785 schema_version: u16,
2786 contract_version: String,
2787 market_id: String,
2788 stream_id: String,
2789 sequence: String,
2790 server_time_ms: u64,
2791 best_bid: Option<PlatformBookLevel>,
2792 best_ask: Option<PlatformBookLevel>,
2793 },
2794 Trade {
2795 schema_version: u16,
2796 contract_version: String,
2797 market_id: String,
2798 server_time_ms: u64,
2799 trade: PlatformTrade,
2800 },
2801 MarketStatus {
2802 schema_version: u16,
2803 contract_version: String,
2804 market_id: String,
2805 server_time_ms: u64,
2806 status: PlatformMarketState,
2807 },
2808 Heartbeat {
2809 schema_version: u16,
2810 contract_version: String,
2811 market_id: String,
2812 server_time_ms: u64,
2813 },
2814}
2815
2816#[cfg(test)]
2817mod tests {
2818 use super::*;
2819
2820 #[test]
2821 fn public_platform_fixtures_decode_strictly() {
2822 let discovery: PlatformDiscoveryResponse =
2823 serde_json::from_str(PLATFORM_CAPABILITIES_FIXTURE).unwrap();
2824 let service_status: PlatformServiceStatusResponse =
2825 serde_json::from_str(PLATFORM_SERVICE_STATUS_FIXTURE).unwrap();
2826 let graph = PlatformActionGraphResponse::foundation();
2827 let assets: PlatformAssetsResponse = serde_json::from_str(PLATFORM_ASSETS_FIXTURE).unwrap();
2828 let swap_quote: PlatformSwapQuoteResponse =
2829 serde_json::from_str(PLATFORM_SWAP_QUOTE_FIXTURE).unwrap();
2830 let markets: PlatformMarketsResponse =
2831 serde_json::from_str(PLATFORM_MARKETS_FIXTURE).unwrap();
2832 let book: PlatformBookSnapshotResponse =
2833 serde_json::from_str(PLATFORM_BOOK_FIXTURE).unwrap();
2834 let bbo: PlatformBestBidAskResponse = serde_json::from_str(PLATFORM_BBO_FIXTURE).unwrap();
2835 let fees: PlatformFeeScheduleResponse =
2836 serde_json::from_str(PLATFORM_FEES_FIXTURE).unwrap();
2837 let status: PlatformMarketStatusResponse =
2838 serde_json::from_str(PLATFORM_STATUS_FIXTURE).unwrap();
2839 let candles: PlatformCandlesResponse =
2840 serde_json::from_str(PLATFORM_CANDLES_FIXTURE).unwrap();
2841 let mark: PlatformMarkResponse = serde_json::from_str(PLATFORM_MARK_FIXTURE).unwrap();
2842 let execution_status: PlatformExecutionStatusResponse =
2843 serde_json::from_str(PLATFORM_EXECUTION_STATUS_FIXTURE).unwrap();
2844 let twaps: PlatformTwapsResponse = serde_json::from_str(PLATFORM_TWAPS_FIXTURE).unwrap();
2845 let twap_challenge: PlatformTwapChallengeResponse =
2846 serde_json::from_str(PLATFORM_TWAP_CHALLENGE_FIXTURE).unwrap();
2847 let twap_prepare: PlatformTwapPrepareResponse =
2848 serde_json::from_str(PLATFORM_TWAP_PREPARE_FIXTURE).unwrap();
2849 let twap_submit: PlatformTwapSubmitResponse =
2850 serde_json::from_str(PLATFORM_TWAP_SUBMIT_FIXTURE).unwrap();
2851 let portfolio_history: PlatformPortfolioHistoryResponse =
2852 serde_json::from_str(PLATFORM_PORTFOLIO_HISTORY_FIXTURE).unwrap();
2853 let portfolio: PlatformPortfolioResponse =
2854 serde_json::from_str(PLATFORM_PORTFOLIO_FIXTURE).unwrap();
2855 let rewards: PlatformRewardsResponse =
2856 serde_json::from_str(PLATFORM_REWARDS_FIXTURE).unwrap();
2857 let referrals: PlatformReferralsResponse =
2858 serde_json::from_str(PLATFORM_REFERRALS_FIXTURE).unwrap();
2859 let referral_link: PlatformReferralLinkResponse =
2860 serde_json::from_str(PLATFORM_REFERRAL_LINK_FIXTURE).unwrap();
2861 let referral_claim: PlatformReferralClaimResponse =
2862 serde_json::from_str(PLATFORM_REFERRAL_CLAIM_FIXTURE).unwrap();
2863 let vault_status: PlatformVaultStatusResponse =
2864 serde_json::from_str(PLATFORM_VAULT_STATUS_FIXTURE).unwrap();
2865 let vault_pause: PlatformVaultPausePrepareResponse =
2866 serde_json::from_str(PLATFORM_VAULT_PAUSE_PREPARE_FIXTURE).unwrap();
2867 let vault_setup: PlatformVaultSetupPrepareResponse =
2868 serde_json::from_str(PLATFORM_VAULT_SETUP_PREPARE_FIXTURE).unwrap();
2869 let vault_delegate: PlatformVaultDelegatePrepareResponse =
2870 serde_json::from_str(PLATFORM_VAULT_DELEGATE_PREPARE_FIXTURE).unwrap();
2871 let vault_policy: PlatformVaultPolicyPrepareResponse =
2872 serde_json::from_str(PLATFORM_VAULT_POLICY_PREPARE_FIXTURE).unwrap();
2873 let vault_deposit: PlatformVaultDepositPrepareResponse =
2874 serde_json::from_str(PLATFORM_VAULT_DEPOSIT_PREPARE_FIXTURE).unwrap();
2875 let vault_withdraw: PlatformVaultWithdrawPrepareResponse =
2876 serde_json::from_str(PLATFORM_VAULT_WITHDRAW_PREPARE_FIXTURE).unwrap();
2877 let vault_submit: PlatformVaultSubmitResponse =
2878 serde_json::from_str(PLATFORM_VAULT_SUBMIT_FIXTURE).unwrap();
2879 let bugs: PlatformBugsResponse = serde_json::from_str(PLATFORM_BUGS_FIXTURE).unwrap();
2880 let bug_submit: PlatformBugSubmitResponse =
2881 serde_json::from_str(PLATFORM_BUG_SUBMIT_FIXTURE).unwrap();
2882 let trades: PlatformTradesResponse = serde_json::from_str(PLATFORM_TRADES_FIXTURE).unwrap();
2883 let account: PlatformAccountSnapshotResponse =
2884 serde_json::from_str(PLATFORM_ACCOUNT_FIXTURE).unwrap();
2885 let maker_reputation: PlatformMakerReputationResponse =
2886 serde_json::from_str(PLATFORM_MAKER_REPUTATION_FIXTURE).unwrap();
2887 let maker_status: PlatformMakerStatusResponse =
2888 serde_json::from_str(PLATFORM_MAKER_STATUS_FIXTURE).unwrap();
2889 let maker_stream: PlatformMakerEvent =
2890 serde_json::from_str(PLATFORM_MAKER_STREAM_FIXTURE).unwrap();
2891 let twap_stream: PlatformTwapEvent =
2892 serde_json::from_str(PLATFORM_TWAP_STREAM_FIXTURE).unwrap();
2893 let execution_stream: PlatformExecutionEvent =
2894 serde_json::from_str(PLATFORM_EXECUTION_STREAM_FIXTURE).unwrap();
2895 let order_challenge: PlatformOrderChallengeResponse =
2896 serde_json::from_str(PLATFORM_ORDER_CHALLENGE_FIXTURE).unwrap();
2897 let order_prepare: PlatformOrderPrepareResponse =
2898 serde_json::from_str(PLATFORM_ORDER_PREPARE_FIXTURE).unwrap();
2899 let order_submit: PlatformOrderSubmitResponse =
2900 serde_json::from_str(PLATFORM_ORDER_SUBMIT_FIXTURE).unwrap();
2901 let order_status: PlatformOrderStatusResponse =
2902 serde_json::from_str(PLATFORM_ORDER_STATUS_FIXTURE).unwrap();
2903
2904 assert_eq!(discovery.schema_version, PLATFORM_SCHEMA_VERSION);
2905 assert_eq!(service_status.status, PlatformServiceState::Operational);
2906 assert_eq!(service_status.available_operations, 59);
2907 assert_eq!(graph.entry_operation_id, "platform.capabilities.read");
2908 assert_eq!(graph.operations.len(), 70);
2909 assert_eq!(maker_reputation.tier, PlatformMakerReputationTier::Gold);
2910 assert_eq!(maker_status.active_products, 3);
2911 match &maker_stream {
2912 PlatformMakerEvent::MakerSnapshot { status, fills, .. } => {
2913 assert_eq!(status.active_products, maker_status.active_products);
2914 assert_eq!(fills.len(), 1);
2915 assert_eq!(fills[0].product, PlatformMakerProduct::Strand);
2916 }
2917 other => panic!("maker stream fixture must be a snapshot, got {other:?}"),
2918 }
2919 match &twap_stream {
2920 PlatformTwapEvent::TwapsSnapshot {
2921 twaps: streamed, ..
2922 } => {
2923 assert_eq!(streamed, &twaps.twaps);
2924 }
2925 other => panic!("twap stream fixture must be a snapshot, got {other:?}"),
2926 }
2927 match &execution_stream {
2928 PlatformExecutionEvent::ExecutionsSnapshot {
2929 executions,
2930 unknown_execution_ids,
2931 ..
2932 } => {
2933 assert_eq!(executions.len(), 2);
2934 assert_eq!(executions[0].execution_id, execution_status.execution_id);
2935 assert_eq!(unknown_execution_ids.len(), 1);
2936 }
2937 other => panic!("execution stream fixture must be a snapshot, got {other:?}"),
2938 }
2939 assert_eq!(maker_status.strands.len(), 1);
2940 assert_eq!(maker_status.currents.len(), 1);
2941 assert!(maker_status
2942 .intent
2943 .as_ref()
2944 .is_some_and(|intent| intent.active));
2945 assert_eq!(portfolio.balances.len(), 2);
2946 assert_eq!(portfolio.positions.len(), 1);
2947 assert!(portfolio.valuation_complete);
2948 assert_eq!(portfolio.equity_usd_micros.as_deref(), Some("439989500"));
2949 assert!(graph
2950 .operations
2951 .iter()
2952 .any(|operation| operation.id == "twap.place.submit"));
2953 assert!(graph
2954 .operations
2955 .iter()
2956 .any(|operation| operation.id == "twap.cancel.submit"));
2957 assert_eq!(discovery.capabilities.len(), 5);
2958 assert!(!discovery.authority.accepts_private_keys);
2959 assert_eq!(assets.assets.len(), 2);
2960 assert_eq!(swap_quote.input_asset_id, assets.assets[0].asset_id);
2961 assert_eq!(swap_quote.output_asset_id, assets.assets[1].asset_id);
2962 assert_eq!(markets.markets.len(), 1);
2963 assert_eq!(markets.markets[0].base_asset_id, assets.assets[0].asset_id);
2964 assert_eq!(markets.markets[0].quote_asset_id, assets.assets[1].asset_id);
2965 assert_eq!(book.sequence, "42");
2966 assert_eq!(bbo.best_bid.unwrap().price_atoms, "149990000");
2967 assert_eq!(fees.maximum_immediate_execution_fee_bps, 10);
2968 assert_eq!(status.status, PlatformMarketState::Active);
2969 assert_eq!(candles.candles.len(), 2);
2970 assert_eq!(mark.price_atoms_per_base_unit.as_deref(), Some("149995000"));
2971 assert_eq!(execution_status.status, PlatformExecutionState::Confirmed);
2972 assert_eq!(
2973 execution_status.settlement,
2974 PlatformSettlementState::Confirmed
2975 );
2976 assert_eq!(twaps.twaps[0].fills.len(), 1);
2977 assert_eq!(twaps.twaps[0].slices_executed, 2);
2978 assert_eq!(twap_challenge.action, PlatformTwapControlAction::Place);
2979 assert_eq!(twap_prepare.twap_id, twap_challenge.twap_id);
2980 assert_eq!(twap_submit.twap_control_id, twap_prepare.twap_control_id);
2981 assert_eq!(portfolio_history.points.len(), 2);
2982 assert_eq!(rewards.standings.len(), 2);
2983 assert!(referrals.enabled);
2984 assert_eq!(referral_link.status, "pending_first_fill");
2985 assert_eq!(referral_claim.status, "requested");
2986 assert_eq!(vault_status.state, PlatformVaultState::Active);
2987 assert_eq!(
2988 vault_status.session.as_ref().unwrap().state,
2989 PlatformVaultSessionState::Active
2990 );
2991 assert!(vault_pause.paused);
2992 assert!(vault_pause.owner_signature_required);
2993 assert_eq!(vault_setup.mode, PlatformVaultSetupMode::Create);
2994 assert!(vault_setup.permanent);
2995 assert_eq!(vault_delegate.action, PlatformVaultDelegateAction::Revoke);
2996 assert!(vault_delegate.owner_signature_required);
2997 assert_eq!(
2998 vault_policy.withdrawal_access.mode,
2999 PlatformVaultWithdrawalMode::Restricted
3000 );
3001 assert!(vault_policy.owner_signature_required);
3002 assert_eq!(vault_deposit.amount_atoms, "10000000");
3003 assert!(vault_deposit.owner_signature_required);
3004 assert_eq!(vault_withdraw.amount_atoms, "5000000");
3005 assert!(vault_withdraw.owner_signature_required);
3006 assert!(vault_withdraw.sponsored);
3007 assert!(vault_withdraw.preparation_id.starts_with("vp_"));
3008 assert_eq!(vault_submit.action, PlatformVaultAction::Deposit);
3009 assert_eq!(
3010 vault_submit.status,
3011 PlatformVaultSubmissionStatus::Submitted
3012 );
3013 assert!(vault_submit.sponsored);
3014 assert_eq!(vault_submit.failure_code, None);
3015 assert_eq!(bugs.reports[0].status, PlatformBugStatus::Confirmed);
3016 assert_eq!(bug_submit.status, PlatformBugStatus::Pending);
3017 assert_eq!(trades.trades.len(), 1);
3018 assert_eq!(account.orders.len(), 1);
3019 assert_eq!(account.fills.len(), 1);
3020 assert_eq!(order_challenge.action, PlatformOrderAction::Place);
3021 assert_eq!(order_prepare.order_ids, order_challenge.order_ids);
3022 assert_eq!(order_submit.order_ids, order_challenge.order_ids);
3023 assert_eq!(order_status.order_control_id, order_submit.order_control_id);
3024 assert_eq!(order_status.status, PlatformOrderControlStatus::Submitting);
3025 }
3026
3027 #[test]
3028 fn public_platform_response_rejects_unreviewed_fields() {
3029 let mut value: serde_json::Value =
3030 serde_json::from_str(PLATFORM_CAPABILITIES_FIXTURE).unwrap();
3031 value
3032 .as_object_mut()
3033 .unwrap()
3034 .insert("unexpected_field".to_owned(), serde_json::Value::Bool(true));
3035 assert!(serde_json::from_value::<PlatformDiscoveryResponse>(value).is_err());
3036
3037 let mut account_event: serde_json::Value =
3038 serde_json::from_str(PLATFORM_ACCOUNT_FIXTURE).unwrap();
3039 let event = account_event.as_object_mut().unwrap();
3040 event.insert("type".to_owned(), serde_json::json!("account_snapshot"));
3041 event.insert(
3042 "stream_id".to_owned(),
3043 serde_json::json!("account_stream_66666666666666666666666666666666"),
3044 );
3045 event.insert("sequence".to_owned(), serde_json::json!("1"));
3046 event.insert("unexpected_field".to_owned(), serde_json::json!(true));
3047 assert!(serde_json::from_value::<PlatformAccountEvent>(account_event).is_err());
3048 }
3049
3050 #[test]
3051 fn platform_graph_availability_is_projected_from_live_capabilities() {
3052 let mut graph = PlatformActionGraphResponse::foundation();
3053 let live = std::collections::BTreeSet::from([
3054 "platform.discover".to_owned(),
3055 "graphs.read".to_owned(),
3056 "orders.replace".to_owned(),
3057 ]);
3058
3059 graph.project_availability(&live);
3060
3061 for operation in &graph.operations {
3062 assert_eq!(
3063 operation.available,
3064 live.contains(&operation.capability_id),
3065 "operation {} did not follow capability {}",
3066 operation.id,
3067 operation.capability_id,
3068 );
3069 }
3070 assert!(graph
3071 .workflows
3072 .iter()
3073 .flat_map(|workflow| &workflow.nodes)
3074 .filter(|node| node.kind != PlatformActionKind::ExternalSignature)
3075 .all(|node| {
3076 node.available
3077 == node
3078 .capability_id
3079 .as_ref()
3080 .is_some_and(|capability_id| live.contains(capability_id))
3081 }));
3082 assert!(graph
3083 .workflows
3084 .iter()
3085 .flat_map(|workflow| &workflow.nodes)
3086 .filter(|node| node.kind == PlatformActionKind::ExternalSignature)
3087 .all(|node| node.available));
3088 }
3089
3090 #[test]
3091 fn atomic_order_batch_request_is_strict_and_typed() {
3092 let request: PlatformOrderChallengeRequest = serde_json::from_value(serde_json::json!({
3093 "action": "batch",
3094 "owner_wallet": "11111111111111111111111111111111",
3095 "session_public_key": "22222222222222222222222222222222",
3096 "operations": [
3097 {
3098 "action": "cancel",
3099 "order_id": "order_11111111111111111111111111111111"
3100 },
3101 {
3102 "action": "replace",
3103 "order_id": "order_22222222222222222222222222222222",
3104 "account_sequence": "8",
3105 "client_order_id": "replacement-8",
3106 "side": "sell",
3107 "order_type": "post_only",
3108 "limit_price_atoms": "151000000",
3109 "size_atoms": "2000000"
3110 }
3111 ]
3112 }))
3113 .unwrap();
3114 let PlatformOrderChallengeRequest::Batch { operations, .. } = request else {
3115 panic!("expected batch request");
3116 };
3117 assert_eq!(operations.len(), 2);
3118 assert!(matches!(
3119 &operations[1],
3120 PlatformOrderBatchOperation::Replace { account_sequence: Some(sequence), .. }
3121 if sequence == "8"
3122 ));
3123
3124 let place: PlatformOrderChallengeRequest = serde_json::from_value(serde_json::json!({
3128 "action": "place",
3129 "owner_wallet": "11111111111111111111111111111111",
3130 "session_public_key": "22222222222222222222222222222222",
3131 "client_order_id": "first-order",
3132 "side": "buy",
3133 "order_type": "post_only",
3134 "limit_price_atoms": "150000000",
3135 "size_atoms": "1000000"
3136 }))
3137 .unwrap();
3138 assert!(matches!(
3139 place,
3140 PlatformOrderChallengeRequest::Place {
3141 account_sequence: None,
3142 ..
3143 }
3144 ));
3145 assert!(!serde_json::to_string(&place)
3146 .unwrap()
3147 .contains("account_sequence"));
3148
3149 assert!(
3150 serde_json::from_value::<PlatformOrderChallengeRequest>(serde_json::json!({
3151 "action": "batch",
3152 "owner_wallet": "11111111111111111111111111111111",
3153 "session_public_key": "22222222222222222222222222222222",
3154 "operations": [{
3155 "action": "cancel",
3156 "order_id": "order_11111111111111111111111111111111",
3157 "implementation": "hidden"
3158 }]
3159 }))
3160 .is_err()
3161 );
3162 }
3163
3164 #[test]
3165 fn persistent_order_commands_default_to_no_self_trade_policy() {
3166 let frame: PlatformOrderCommandClientFrame = serde_json::from_value(serde_json::json!({
3167 "type": "command",
3168 "request_id": "agent-1",
3169 "sequence": "1",
3170 "command": {
3171 "type": "challenge",
3172 "self_trade_prevention": "cancel_maker",
3173 "request": {
3174 "action": "cancel_all",
3175 "owner_wallet": "11111111111111111111111111111111",
3176 "session_public_key": "22222222222222222222222222222222"
3177 }
3178 }
3179 }))
3180 .unwrap();
3181 assert!(matches!(
3182 frame,
3183 PlatformOrderCommandClientFrame::Command {
3184 command: PlatformOrderCommand::Challenge {
3185 self_trade_prevention: PlatformSelfTradePrevention::CancelMaker,
3186 ..
3187 },
3188 ..
3189 }
3190 ));
3191 let default_frame: PlatformOrderCommandClientFrame =
3192 serde_json::from_value(serde_json::json!({
3193 "type": "command",
3194 "request_id": "agent-1",
3195 "sequence": "1",
3196 "command": {
3197 "type": "challenge",
3198 "request": {
3199 "action": "cancel_all",
3200 "owner_wallet": "11111111111111111111111111111111",
3201 "session_public_key": "22222222222222222222222222222222"
3202 }
3203 }
3204 }))
3205 .unwrap();
3206 assert!(matches!(
3207 default_frame,
3208 PlatformOrderCommandClientFrame::Command {
3209 command: PlatformOrderCommand::Challenge {
3210 self_trade_prevention: PlatformSelfTradePrevention::None,
3211 ..
3212 },
3213 ..
3214 }
3215 ));
3216 }
3217
3218 #[test]
3219 fn prepare_requests_accept_a_signed_challenge_or_the_operation_itself() {
3220 let signed: PlatformOrderPrepareRequest = serde_json::from_value(serde_json::json!({
3221 "challenge_id": "oc_0123456789abcdef0123456789abcdef",
3222 "authorization_signature": "1111",
3223 }))
3224 .unwrap();
3225 assert!(matches!(signed, PlatformOrderPrepareRequest::Authorized(_)));
3226 let direct: PlatformOrderPrepareRequest = serde_json::from_value(serde_json::json!({
3227 "action": "cancel_all",
3228 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3229 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3230 }))
3231 .unwrap();
3232 assert!(matches!(
3233 direct,
3234 PlatformOrderPrepareRequest::Direct(PlatformOrderChallengeRequest::CancelAll { .. })
3235 ));
3236 assert!(
3238 serde_json::from_value::<PlatformOrderPrepareRequest>(serde_json::json!({
3239 "challenge_id": "oc_0123456789abcdef0123456789abcdef",
3240 "authorization_signature": "1111",
3241 "extra": true,
3242 }))
3243 .is_err()
3244 );
3245 let twap: PlatformTwapPrepareRequest = serde_json::from_value(serde_json::json!({
3246 "action": "cancel",
3247 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3248 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3249 "twap_id": "twap_0123456789abcdef0123456789abcdef",
3250 }))
3251 .unwrap();
3252 assert!(matches!(twap, PlatformTwapPrepareRequest::Direct(_)));
3253 let execution: crate::ExecutionPrepareRequest = serde_json::from_value(serde_json::json!({
3254 "quote_id": "quote_0123456789abcdef0123456789abcdef",
3255 "owner_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3256 "session_public_key": "9Uu7cLBgfMk233BAjMvTS8XJy6KbZK7oQ7NXuCTi3Fg2",
3257 }))
3258 .unwrap();
3259 assert!(matches!(
3260 execution,
3261 crate::ExecutionPrepareRequest::Direct(_)
3262 ));
3263 }
3264
3265 #[test]
3266 fn maker_control_requests_are_tagged_exact_and_amount_safe() {
3267 let strand_upsert: PlatformMakerStrandPrepareRequest =
3268 serde_json::from_value(serde_json::json!({
3269 "action": "upsert",
3270 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3271 "enabled": true,
3272 "async_only": false,
3273 "sync_spread_ticks": 1,
3274 "mid_price_atoms": "123000000",
3275 "max_exposure_base_atoms": "1000000",
3276 "bid_offsets_ticks": vec![1; 16],
3277 "ask_offsets_ticks": vec![1; 16],
3278 "bid_sizes_base_atoms": vec!["1"; 16],
3279 "ask_sizes_base_atoms": vec!["1"; 16],
3280 "valid_until_slot": "0"
3281 }))
3282 .unwrap();
3283 let serialized = serde_json::to_value(&strand_upsert).unwrap();
3284 assert_eq!(serialized["max_exposure_base_atoms"], "1000000");
3285 assert!(serialized.get("max_exposure_base_lots").is_none());
3286
3287 let legacy_strand: PlatformMakerStrandPrepareRequest =
3290 serde_json::from_value(serde_json::json!({
3291 "action": "upsert",
3292 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3293 "enabled": true,
3294 "async_only": false,
3295 "sync_spread_ticks": 1,
3296 "mid_price_atoms": "123000000",
3297 "max_exposure_base_lots": "1000000",
3298 "bid_offsets_ticks": vec![1; 16],
3299 "ask_offsets_ticks": vec![1; 16],
3300 "bid_sizes_base_lots": vec!["1"; 16],
3301 "ask_sizes_base_lots": vec!["1"; 16],
3302 "valid_until_slot": "0"
3303 }))
3304 .unwrap();
3305 assert_eq!(serde_json::to_value(legacy_strand).unwrap(), serialized);
3306
3307 let strand: PlatformMakerStrandPrepareRequest = serde_json::from_value(serde_json::json!({
3308 "action": "recenter",
3309 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3310 "new_mid_price_atoms": "123000000",
3311 "valid_until_slot": "0"
3312 }))
3313 .unwrap();
3314 assert!(matches!(
3315 strand,
3316 PlatformMakerStrandPrepareRequest::Recenter { .. }
3317 ));
3318
3319 let current: PlatformMakerCurrentPrepareRequest =
3320 serde_json::from_value(serde_json::json!({
3321 "action": "cancel",
3322 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL"
3323 }))
3324 .unwrap();
3325 assert!(matches!(
3326 current,
3327 PlatformMakerCurrentPrepareRequest::Cancel { .. }
3328 ));
3329 assert!(
3330 serde_json::from_value::<PlatformMakerCurrentPrepareRequest>(serde_json::json!({
3331 "action": "cancel",
3332 "maker_wallet": "5Ji61Fbeb22Yntgv1hhHeSSLgdEdZchHeM1Tv1MjGhSL",
3333 "oracle_price": 123.45
3334 }))
3335 .is_err()
3336 );
3337 }
3338}