@metaflux-dex/client 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/client.d.ts +33 -1
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +74 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/index.d.ts +4 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/native/actions.d.ts +7 -1
  10. package/dist/native/actions.d.ts.map +1 -1
  11. package/dist/native/actions.js +113 -1
  12. package/dist/native/actions.js.map +1 -1
  13. package/dist/native/digest.d.ts +1 -0
  14. package/dist/native/digest.d.ts.map +1 -1
  15. package/dist/native/digest.js +11 -0
  16. package/dist/native/digest.js.map +1 -1
  17. package/dist/types/cross-chain.d.ts +8 -0
  18. package/dist/types/cross-chain.d.ts.map +1 -0
  19. package/dist/types/cross-chain.js +9 -0
  20. package/dist/types/cross-chain.js.map +1 -0
  21. package/dist/types/encrypted.d.ts +5 -0
  22. package/dist/types/encrypted.d.ts.map +1 -1
  23. package/dist/types/fba.d.ts +9 -0
  24. package/dist/types/fba.d.ts.map +1 -0
  25. package/dist/types/fba.js +8 -0
  26. package/dist/types/fba.js.map +1 -0
  27. package/dist/types/index.d.ts +5 -2
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/dist/types/info/core.d.ts +5 -1
  30. package/dist/types/info/core.d.ts.map +1 -1
  31. package/dist/types/info/index.d.ts +1 -1
  32. package/dist/types/info/index.d.ts.map +1 -1
  33. package/dist/types/info/reads.d.ts.map +1 -1
  34. package/dist/types/rfq.d.ts +15 -0
  35. package/dist/types/rfq.d.ts.map +1 -0
  36. package/dist/types/rfq.js +9 -0
  37. package/dist/types/rfq.js.map +1 -0
  38. package/dist/types/vault.d.ts +4 -0
  39. package/dist/types/vault.d.ts.map +1 -1
  40. package/dist/ws/ws.d.ts +46 -2
  41. package/dist/ws/ws.d.ts.map +1 -1
  42. package/dist/ws/ws.js +237 -7
  43. package/dist/ws/ws.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/client.ts +120 -2
  46. package/src/index.ts +19 -0
  47. package/src/native/actions.ts +135 -0
  48. package/src/native/digest.ts +12 -0
  49. package/src/types/cross-chain.ts +32 -0
  50. package/src/types/encrypted.ts +23 -0
  51. package/src/types/fba.ts +32 -0
  52. package/src/types/index.ts +5 -1
  53. package/src/types/info/core.ts +28 -13
  54. package/src/types/info/index.ts +1 -0
  55. package/src/types/info/reads.ts +17 -5
  56. package/src/types/rfq.ts +55 -0
  57. package/src/types/vault.ts +21 -0
  58. package/src/ws/ws.ts +372 -14
@@ -14,11 +14,13 @@ import {
14
14
  validateAddress,
15
15
  validateCloid,
16
16
  validateDecimalString,
17
+ validateI128,
17
18
  validateMarket,
18
19
  validateU8,
19
20
  validateU16,
20
21
  validateU32,
21
22
  validateU64,
23
+ validateU128,
22
24
  } from './digest.js';
23
25
  import type {
24
26
  AgentSetAbstraction,
@@ -31,7 +33,11 @@ import type {
31
33
  CancelByCloid,
32
34
  ClaimRewards,
33
35
  ConvertToMultiSigUser,
36
+ CoreSide,
34
37
  CreateVault,
38
+ CrossChainSend,
39
+ EncryptedOrderSubmit,
40
+ FbaSubmit,
35
41
  LinkStakingUser,
36
42
  MbWithdraw,
37
43
  Modify,
@@ -49,6 +55,8 @@ import type {
49
55
  NativeSpotOrder,
50
56
  PriorityBid,
51
57
  RegisterMetaliquidityOperator,
58
+ RfqAccept,
59
+ RfqRequest,
52
60
  ScheduleCancel,
53
61
  SetDisplayName,
54
62
  SetMetaliquidityWhitelist,
@@ -63,6 +71,7 @@ import type {
63
71
  UserDexAbstraction,
64
72
  UserPortfolioMargin,
65
73
  UserSetAbstraction,
74
+ VaultDistribute,
66
75
  VaultModify,
67
76
  VaultTransfer,
68
77
  VaultWithdraw,
@@ -665,6 +674,19 @@ export function buildNativeVaultWithdrawAction(params: VaultWithdraw): string {
665
674
  );
666
675
  }
667
676
 
677
+ /// `vault_distribute` — follower deposits USD into a vault, minting shares at
678
+ /// the current NAV. The deposit amount rides the **`pnl`** field (a legacy node
679
+ /// name) as a positive decimal string; `vault_id` is a bare number. Wrapper key
680
+ /// is `params`. Forward-compat: see the module note on the RFQ/FBA builders.
681
+ export function buildNativeVaultDistributeAction(params: VaultDistribute): string {
682
+ validateU64(params.vault_id, 'vault_id');
683
+ validateDecimalString(params.pnl, 'pnl');
684
+ return wrapParams(
685
+ 'vault_distribute',
686
+ `{${jsonStr('vault_id')}:${params.vault_id},${jsonStr('pnl')}:${jsonStr(params.pnl)}}`,
687
+ );
688
+ }
689
+
668
690
  // ---- MetaBridge ----
669
691
 
670
692
  /// `mb_withdraw` — withdraw cross-collateral to a destination chain. `dst_addr`
@@ -818,3 +840,116 @@ export function buildNativeEarnWithdrawAction(
818
840
  const paramsJson = `{${jsonStr('asset')}:${params.asset},${jsonStr('shares')}:${jsonStr(params.shares)}}`;
819
841
  return `{${jsonStr('type')}:${jsonStr('earn_withdraw')},${jsonStr('params')}:${paramsJson}}`;
820
842
  }
843
+
844
+ // ============================================================================
845
+ // RFQ / FBA / cross-chain / encrypted (forward-compat).
846
+ //
847
+ // The node recognizes these action tags but currently lowers them to
848
+ // `UnsupportedAction` on the public `/exchange` path (the real handlers run on
849
+ // the EVM core-writer path). The SDK emits the byte-correct wire shape each core
850
+ // param struct expects, so these become live the moment the node bridges them —
851
+ // no SDK change required. Note the per-action wrapper keys differ:
852
+ // `rfq` / `accept` / `submit` / `msg` / `encrypted` (NOT `params`).
853
+ //
854
+ // Traps mirrored from the node's plain `#[derive(Serialize)]`:
855
+ // - `side` is PascalCase (`"Bid"`/`"Ask"`), distinct from the snake_case
856
+ // `"bid"`/`"ask"` the perp/spot order builders use.
857
+ // - `size` is a `u128` and `limit_px`/`price` are `i128`, emitted as bare JSON
858
+ // numbers (the size/px planes can exceed 2^53, so they ride as `bigint`).
859
+ // - `limit_px` (RFQ) / `stp_group` (RFQ + FBA) carry no serde default on the
860
+ // node, so the key MUST be present — emit `null` when absent, do NOT omit.
861
+ // - byte arrays (`recipient`, `ciphertext`, `commitment`) are JSON arrays of
862
+ // byte-numbers, NOT 0x-hex strings.
863
+ // ============================================================================
864
+
865
+ /// Render a PascalCase core side token (`"Bid"`/`"Ask"`), failing loud on any
866
+ /// other value (a snake_case `"bid"`/`"ask"` here would be silently rejected by
867
+ /// the core handler).
868
+ function coreSideToken(side: CoreSide, field: string): string {
869
+ if (side !== 'Bid' && side !== 'Ask') {
870
+ throw new RangeError(`${field} must be "Bid" or "Ask" (PascalCase CoreSide)`);
871
+ }
872
+ return jsonStr(side);
873
+ }
874
+
875
+ /// Serialize a byte buffer as a JSON array of unsigned byte-numbers, optionally
876
+ /// pinning an exact length.
877
+ function byteArrayJson(bytes: Uint8Array, field: string, len?: number): string {
878
+ if (!(bytes instanceof Uint8Array)) {
879
+ throw new RangeError(`${field} must be a Uint8Array`);
880
+ }
881
+ if (len !== undefined && bytes.length !== len) {
882
+ throw new RangeError(`${field} must be exactly ${len} bytes`);
883
+ }
884
+ return `[${Array.from(bytes).join(',')}]`;
885
+ }
886
+
887
+ /// `rfq_request` — taker opens an RFQ session. Wrapper key is **`rfq`**. `side`
888
+ /// is PascalCase; `limit_px` (`i128`) and `stp_group` (`u64`) keys are ALWAYS
889
+ /// present (`null` when absent — the node has no serde default).
890
+ export function buildNativeRfqRequestAction(params: RfqRequest): string {
891
+ validateMarket(params.market);
892
+ validateU128(params.size, 'size');
893
+ validateU64(params.expiry_ms, 'expiry_ms');
894
+ if (params.limit_px !== null) {
895
+ validateI128(params.limit_px, 'limit_px');
896
+ }
897
+ if (params.stp_group !== null) {
898
+ validateU64(params.stp_group, 'stp_group');
899
+ }
900
+ const limitPx = params.limit_px === null ? 'null' : params.limit_px.toString();
901
+ const stpGroup = params.stp_group === null ? 'null' : `${params.stp_group}`;
902
+ const rfqJson = `{${jsonStr('market')}:${params.market},${jsonStr('side')}:${coreSideToken(params.side, 'side')},${jsonStr('size')}:${params.size},${jsonStr('limit_px')}:${limitPx},${jsonStr('expiry_ms')}:${params.expiry_ms},${jsonStr('stp_group')}:${stpGroup}}`;
903
+ return `{${jsonStr('type')}:${jsonStr('rfq_request')},${jsonStr('rfq')}:${rfqJson}}`;
904
+ }
905
+
906
+ /// `rfq_accept` — taker crosses against a specific resting quote. Wrapper key is
907
+ /// **`accept`** (NOT `rfq`).
908
+ export function buildNativeRfqAcceptAction(params: RfqAccept): string {
909
+ validateU64(params.rfq_id, 'rfq_id');
910
+ validateU32(params.quote_idx, 'quote_idx');
911
+ validateU128(params.size, 'size');
912
+ const acceptJson = `{${jsonStr('rfq_id')}:${params.rfq_id},${jsonStr('quote_idx')}:${params.quote_idx},${jsonStr('size')}:${params.size}}`;
913
+ return `{${jsonStr('type')}:${jsonStr('rfq_accept')},${jsonStr('accept')}:${acceptJson}}`;
914
+ }
915
+
916
+ /// `fba_submit` — submit into a market's frequent-batch-auction pool. Wrapper
917
+ /// key is **`submit`**. The price field is **`price`** (NOT `limit_px`); `side`
918
+ /// is PascalCase; `stp_group` key is ALWAYS present (`null` when absent).
919
+ export function buildNativeFbaSubmitAction(params: FbaSubmit): string {
920
+ validateMarket(params.market);
921
+ validateU128(params.size, 'size');
922
+ validateI128(params.price, 'price');
923
+ if (params.stp_group !== null) {
924
+ validateU64(params.stp_group, 'stp_group');
925
+ }
926
+ const stpGroup = params.stp_group === null ? 'null' : `${params.stp_group}`;
927
+ const submitJson = `{${jsonStr('market')}:${params.market},${jsonStr('side')}:${coreSideToken(params.side, 'side')},${jsonStr('size')}:${params.size},${jsonStr('price')}:${params.price},${jsonStr('stp_group')}:${stpGroup}}`;
928
+ return `{${jsonStr('type')}:${jsonStr('fba_submit')},${jsonStr('submit')}:${submitJson}}`;
929
+ }
930
+
931
+ /// `cross_chain_send` — initiate a chain-agnostic cross-chain transfer. Wrapper
932
+ /// key is **`msg`**. `recipient` is a 32-byte array; `amount` (`u128`) is a bare
933
+ /// JSON number (NOT hex).
934
+ export function buildNativeCrossChainSendAction(params: CrossChainSend): string {
935
+ validateU32(params.dst_chain_id, 'dst_chain_id');
936
+ const recipient = byteArrayJson(params.recipient, 'recipient', 32);
937
+ validateU32(params.token, 'token');
938
+ validateU128(params.amount, 'amount');
939
+ validateU64(params.nonce, 'nonce');
940
+ const msgJson = `{${jsonStr('dst_chain_id')}:${params.dst_chain_id},${jsonStr('recipient')}:${recipient},${jsonStr('token')}:${params.token},${jsonStr('amount')}:${params.amount},${jsonStr('nonce')}:${params.nonce}}`;
941
+ return `{${jsonStr('type')}:${jsonStr('cross_chain_send')},${jsonStr('msg')}:${msgJson}}`;
942
+ }
943
+
944
+ /// `encrypted_order_submit` — submit a threshold-encrypted order. Wrapper key is
945
+ /// **`encrypted`**. Only 3 fields — DISTINCT from `submit_encrypted_order`
946
+ /// (5 fields, key `params`). `ciphertext`/`commitment` are byte arrays.
947
+ export function buildNativeEncryptedOrderSubmitAction(
948
+ params: EncryptedOrderSubmit,
949
+ ): string {
950
+ const ct = byteArrayJson(params.ciphertext, 'ciphertext');
951
+ const cm = byteArrayJson(params.commitment, 'commitment', 32);
952
+ validateU64(params.reveal_deadline_ms, 'reveal_deadline_ms');
953
+ const encJson = `{${jsonStr('ciphertext')}:${ct},${jsonStr('commitment')}:${cm},${jsonStr('reveal_deadline_ms')}:${params.reveal_deadline_ms}}`;
954
+ return `{${jsonStr('type')}:${jsonStr('encrypted_order_submit')},${jsonStr('encrypted')}:${encJson}}`;
955
+ }
@@ -264,6 +264,18 @@ export function validateU128(value: bigint, field: string): void {
264
264
  if (value >= 1n << 128n) throw new RangeError(`${field} overflows u128`);
265
265
  }
266
266
 
267
+ /// Validate an `i128` field passed as a `bigint`, emitted as a bare unquoted
268
+ /// integer literal on the wire (serde i128 JSON number form). Accepts the full
269
+ /// signed-128-bit range `[-2^127, 2^127)`.
270
+ export function validateI128(value: bigint, field: string): void {
271
+ if (typeof value !== 'bigint') {
272
+ throw new RangeError(`${field} must be a bigint`);
273
+ }
274
+ if (value < -(1n << 127n) || value >= 1n << 127n) {
275
+ throw new RangeError(`${field} overflows i128`);
276
+ }
277
+ }
278
+
267
279
  /// Validate a decimal magnitude passed as a string and emitted as a JSON
268
280
  /// **string** on the wire (e.g. spot-margin `amount` / `borrow`, Earn
269
281
  /// `shares`). The server decodes these as a fixed-point `Decimal`, so they must
@@ -0,0 +1,32 @@
1
+ // MTF-native cross-chain action payload type.
2
+ //
3
+ // Forward-compat: the node recognizes the `cross_chain_send` action tag but
4
+ // currently lowers it to `UnsupportedAction` on the public `/exchange` path
5
+ // (the real handler runs on the EVM core-writer path). The SDK emits the
6
+ // byte-correct shape the node's `evm_integration` `CrossChainSendParams`
7
+ // decoder expects, so it goes live the moment the node bridges it.
8
+
9
+ /// `cross_chain_send` — initiate a chain-agnostic cross-chain transfer (queued
10
+ /// to the bridge outbox). Mirrors the node's `evm_integration`
11
+ /// `CrossChainSendParams`. The action envelope wraps this under the key **`msg`**.
12
+ ///
13
+ /// Traps: the action field is `dst_chain_id` (the read-only `CrossChainMsg`
14
+ /// snapshot uses `dst_chain`); under the node's plain `#[derive(Serialize)]`,
15
+ /// `recipient: [u8; 32]` is a JSON **array of 32 byte-numbers** and `amount`
16
+ /// (`u128`) is a JSON **number** — NOT 0x-hex strings.
17
+ export interface CrossChainSend {
18
+ /// Destination chain id (`u32`).
19
+ dst_chain_id: number;
20
+ /// Chain-agnostic 32-byte recipient (EVM = left-padded 20-byte address).
21
+ /// Serializes as a JSON array of 32 byte-numbers — pass a 32-byte
22
+ /// `Uint8Array`.
23
+ recipient: Uint8Array;
24
+ /// MTF asset id (`u32`) — NOT a destination-chain token address.
25
+ token: number;
26
+ /// Amount in the MTF asset's native fixed-point (`u128`). `bigint` — emitted
27
+ /// as a bare JSON number, NOT hex.
28
+ amount: bigint;
29
+ /// Application-supplied idempotency nonce (`u64`); `(sender, nonce)` is the
30
+ /// key.
31
+ nonce: number;
32
+ }
@@ -19,3 +19,26 @@ export interface SubmitEncryptedOrder {
19
19
  /// (`u64`).
20
20
  reveal_deadline_ms: number;
21
21
  }
22
+
23
+ /// `encrypted_order_submit` — submit a threshold-encrypted order under the
24
+ /// node's `evm_integration` `EncryptedOrderSubmitParams`. The action envelope
25
+ /// wraps this under the key **`encrypted`**.
26
+ ///
27
+ /// DISTINCT from `SubmitEncryptedOrder`: that 5-field type backs the *different*
28
+ /// `submit_encrypted_order` tag (key `params`, the real bridged handler). This
29
+ /// 3-field type has **no** `threshold` / `target_block`.
30
+ ///
31
+ /// Forward-compat: the node currently answers this tag with `UnsupportedAction`
32
+ /// on the public `/exchange` path; the SDK emits the byte-correct shape the core
33
+ /// handler will accept once the bridge lands.
34
+ export interface EncryptedOrderSubmit {
35
+ /// Threshold-encrypted order bytes (node decoder bounds this at 4096).
36
+ /// Emitted as a JSON array of byte numbers — pass a `Uint8Array`.
37
+ ciphertext: Uint8Array;
38
+ /// 32-byte `keccak(plaintext‖salt)` commitment. Emitted as a JSON array of
39
+ /// 32 byte numbers — pass a 32-byte `Uint8Array`.
40
+ commitment: Uint8Array;
41
+ /// Absolute consensus-time ms by which a valid plaintext must be revealed
42
+ /// (`u64`).
43
+ reveal_deadline_ms: number;
44
+ }
@@ -0,0 +1,32 @@
1
+ // MTF-native FBA (Frequent Batch Auction) action payload type.
2
+ //
3
+ // Forward-compat: the node recognizes the `fba_submit` action tag but currently
4
+ // lowers it to `UnsupportedAction` on the public `/exchange` path. The SDK emits
5
+ // the byte-correct shape the core `FbaSubmitParams` decoder expects, so it goes
6
+ // live the moment the node bridges the handler — no SDK change required.
7
+
8
+ import type { CoreSide } from './rfq.js';
9
+
10
+ /// `fba_submit` — submit an order into a market's frequent-batch-auction pool.
11
+ /// Mirrors the node's `core_state` `FbaSubmitParams`. The action envelope wraps
12
+ /// this under the key **`submit`**.
13
+ ///
14
+ /// Traps mirrored from the node: `side` is PascalCase (`CoreSide`), the price
15
+ /// field is named **`price`** (NOT `limit_px` as in spot/perp orders), and
16
+ /// `stp_group` carries no serde default so the key must be present (`null` when
17
+ /// absent).
18
+ export interface FbaSubmit {
19
+ /// Target market (`u32`).
20
+ market: number;
21
+ /// Side — serializes PascalCase (`"Bid"`/`"Ask"`).
22
+ side: CoreSide;
23
+ /// Submitted size (`u128`, `>= pool.min_lot`). `bigint` — emitted as a bare
24
+ /// JSON number.
25
+ size: bigint;
26
+ /// Limit / worst-acceptable price (`i128`, `> 0`). Field is **`price`** per
27
+ /// the core struct — NOT `limit_px`. `bigint` — emitted as a bare number.
28
+ price: bigint;
29
+ /// Optional STP group (`u64`). The key is ALWAYS present: `null` when absent
30
+ /// (do NOT omit).
31
+ stp_group: number | null;
32
+ }
@@ -75,5 +75,9 @@ export type {
75
75
  VaultTransfer,
76
76
  VaultModify,
77
77
  VaultWithdraw,
78
+ VaultDistribute,
78
79
  } from './vault.js';
79
- export type { SubmitEncryptedOrder } from './encrypted.js';
80
+ export type { SubmitEncryptedOrder, EncryptedOrderSubmit } from './encrypted.js';
81
+ export type { CoreSide, RfqRequest, RfqAccept } from './rfq.js';
82
+ export type { FbaSubmit } from './fba.js';
83
+ export type { CrossChainSend } from './cross-chain.js';
@@ -97,22 +97,28 @@ export interface Funding {
97
97
  next_payment_ts: number;
98
98
  }
99
99
 
100
+ /// Market kind. The deployed gateway emits lowercase `"perp"` / `"spot"`.
101
+ export type MarketKind = 'perp' | 'spot';
102
+
100
103
  /// `market_info` / `markets` element — rich per-market metadata.
101
104
  ///
102
- /// `mark_px` is the on-book mark in the 1e8 fixed-point plane; `oracle_px` is
103
- /// the index price in the whole-USDC plane. Both are `"0"` when unset. (These
104
- /// two price fields are emitted by the node `market_record` builder; they are
105
- /// not yet listed in the KB field table but are part of the live wire shape.)
105
+ /// `mark_px` and `oracle_px` are whole-USDC decimal strings (tick-snapped;
106
+ /// `"0"` fallback). `sz_decimals` is load-bearing for size encoding raw
107
+ /// order/position `size` = `whole_units × 10^sz_decimals`, NOT derivable from
108
+ /// `step_size`.
106
109
  export interface MarketInfo {
107
110
  /// Canonical asset id.
108
111
  asset_id: number;
109
112
  /// Human-readable market name (e.g. `"BTC"`).
110
113
  name: string;
111
- /// Market kind — currently always `"Perp"`.
112
- kind: string;
113
- /// On-book mark price, 1e8 fixed-point as a decimal string.
114
+ /// Market kind — lowercase `"perp"` / `"spot"`.
115
+ kind: MarketKind;
116
+ /// Size precision: raw order/position `size` = `whole_units × 10^sz_decimals`.
117
+ /// Load-bearing for size encoding — NOT derivable from `step_size`.
118
+ sz_decimals: number;
119
+ /// Mark price, whole-USDC plane as a decimal string (`"0"` fallback).
114
120
  mark_px: string;
115
- /// Oracle/index price, whole-USDC plane as a decimal string.
121
+ /// Oracle/index price, whole-USDC plane as a decimal string (`"0"` fallback).
116
122
  oracle_px: string;
117
123
  /// Tick size (smallest price increment), fixed-point string.
118
124
  tick_size: string;
@@ -201,14 +207,23 @@ export interface FeeTier {
201
207
  }
202
208
 
203
209
  /// `fee_schedule` — protocol fee schedule. Fee rates are decimal bps strings;
204
- /// `burn_ratio` is a decimal fraction string (`"0.30"` = 30%).
210
+ /// `burn_ratio` is a decimal fraction string in `[0, 1]` (`"0.8"` = 80%) — NOT
211
+ /// bps, do not scale it by 10000. `tiers[0]` is the authoritative carrier of
212
+ /// maker/taker when the top-level pair is absent.
205
213
  export interface FeeSchedule {
206
- /// Volume-tier ladder.
214
+ /// Top-level base maker fee, decimal bps string. Present on the deployed
215
+ /// gateway; ABSENT from a node built from current source — fall back to
216
+ /// `tiers[0].maker_bps` when `undefined`.
217
+ maker_bps?: string;
218
+ /// Top-level base taker fee, decimal bps string. See `maker_bps`.
219
+ taker_bps?: string;
220
+ /// Volume-tier ladder (authoritative carrier of maker/taker).
207
221
  tiers: FeeTier[];
208
- /// Builder rebate, decimal bps string.
222
+ /// Max additional builder-code rebate, decimal bps string.
209
223
  builder_rebate_bps: string;
210
- /// Fraction of fees burned, decimal fraction string.
224
+ /// Burn fraction of the non-referrer remainder, decimal fraction string in
225
+ /// `[0, 1]` (NOT bps).
211
226
  burn_ratio: string;
212
- /// Referrer share, decimal bps string.
227
+ /// Referrer share of the base taker take, decimal bps string.
213
228
  referrer_share_bps: string;
214
229
  }
@@ -11,6 +11,7 @@ export type {
11
11
  Tier,
12
12
  MarginMode,
13
13
  MarketInfo,
14
+ MarketKind,
14
15
  Funding,
15
16
  VaultState,
16
17
  StakingState,
@@ -5,18 +5,30 @@
5
5
  // Money magnitudes that can exceed 2^53 are typed `string`.
6
6
 
7
7
  /// One resting order inside an `OpenOrders` response.
8
+ ///
9
+ /// `px` is x1e8 fixed-point (positive canonical price for **both** sides);
10
+ /// `size` is raw lots (`whole × 10^sz_decimals`). `side` is lowercase
11
+ /// `"bid"`/`"ask"`. `oid` / `market_id` / `inserted_at_ms` are bare integers.
12
+ ///
13
+ /// LIVE GATEWAY GAP: a resting order currently reads back with `oid: 0` and
14
+ /// `inserted_at_ms: 0` even though it is on the book — so an order is NOT
15
+ /// reliably cancellable by the `oid` from this snapshot, and it carries no
16
+ /// `cloid`. Until the gateway populates `oid`, the oid-independent workaround
17
+ /// for reconcile / ghost-sweep is the `cancel_all_orders` exchange action
18
+ /// (`Client.cancelAllOrders`, keyed by account / asset) rather than per-oid
19
+ /// cancels.
8
20
  export interface OpenOrder {
9
- /// Server order id.
21
+ /// Server order id. See the note: currently `0` on the gateway.
10
22
  oid: number;
11
23
  /// Asset / market id the order rests on.
12
24
  market_id: number;
13
- /// Order side.
25
+ /// Order side, lowercase `"bid"` / `"ask"`.
14
26
  side: 'bid' | 'ask';
15
- /// Resting price, fixed-point decimal string.
27
+ /// Resting price, x1e8 fixed-point decimal string.
16
28
  px: string;
17
- /// Remaining size, fixed-point decimal string.
29
+ /// Remaining size, raw lots (`whole × 10^sz_decimals`) decimal string.
18
30
  size: string;
19
- /// Insertion timestamp (consensus ms).
31
+ /// Insertion timestamp (consensus ms). See the note: currently `0`.
20
32
  inserted_at_ms: number;
21
33
  }
22
34
 
@@ -0,0 +1,55 @@
1
+ // MTF-native RFQ (Request-for-Quote) action payload types.
2
+ //
3
+ // Forward-compat: the node recognizes the `rfq_request` / `rfq_accept` action
4
+ // tags but currently lowers them to `UnsupportedAction` on the public
5
+ // `/exchange` path (the real handlers run on the EVM core-writer path). The SDK
6
+ // emits the byte-correct wire shape each core param struct expects, so these
7
+ // go live the moment the node bridges them — no SDK change required.
8
+
9
+ /// Order side as the **core** RFQ / FBA action handlers deserialize it:
10
+ /// PascalCase `"Bid"` / `"Ask"`.
11
+ ///
12
+ /// Deliberately distinct from the snake_case `NativeSide` (`"bid"`/`"ask"`)
13
+ /// used by the perp/spot order builders: the node's `core_state::Side` enum
14
+ /// carries no `#[serde(rename_all)]`, so the `rfq_request` / `fba_submit`
15
+ /// payloads expect PascalCase tokens. Reusing the snake_case side would
16
+ /// silently emit `"bid"`/`"ask"` that the core handlers reject.
17
+ export type CoreSide = 'Bid' | 'Ask';
18
+
19
+ /// `rfq_request` — a taker opens an RFQ session asking MMs to quote. Mirrors the
20
+ /// node's `core_state` `RfqRequestParams`. The action envelope wraps this under
21
+ /// the key **`rfq`** (not `params`).
22
+ ///
23
+ /// `limit_px` and `stp_group` carry NO serde default on the node, so the keys
24
+ /// must always be present — an absent value serializes as JSON `null` (the SDK
25
+ /// does NOT skip them).
26
+ export interface RfqRequest {
27
+ /// Market to request a quote on (`u32`).
28
+ market: number;
29
+ /// Taker side — serializes PascalCase (`"Bid"`/`"Ask"`).
30
+ side: CoreSide;
31
+ /// Requested size (`u128`, `> 0`). `bigint` — emitted as a bare JSON number.
32
+ size: bigint;
33
+ /// Optional worst-acceptable price (`i128`). The key is ALWAYS present:
34
+ /// `null` when absent (do NOT omit). `bigint` — emitted as a bare number.
35
+ limit_px: bigint | null;
36
+ /// Server-clock expiry (ms, `u64`). `0` lets the node default to `ts_ms + 5000`.
37
+ expiry_ms: number;
38
+ /// Optional STP group id (`u64`). The key is ALWAYS present: `null` when
39
+ /// absent (do NOT omit).
40
+ stp_group: number | null;
41
+ }
42
+
43
+ /// `rfq_accept` — a taker crosses against a specific resting quote. Mirrors the
44
+ /// node's `RfqAcceptParams`. The action envelope wraps this under the key
45
+ /// **`accept`** — note the family inconsistency (`rfq_request` uses `rfq`,
46
+ /// `rfq_accept` uses `accept`).
47
+ export interface RfqAccept {
48
+ /// Parent RFQ session id (`u64`).
49
+ rfq_id: number;
50
+ /// Index of the accepted quote in the session's quote vector (`u32`).
51
+ quote_idx: number;
52
+ /// Accepted size (`u128`, `<= min(request.size, quote.max_size)`). `bigint` —
53
+ /// emitted as a bare JSON number.
54
+ size: bigint;
55
+ }
@@ -53,3 +53,24 @@ export interface VaultWithdraw {
53
53
  /// Shares to redeem, as a decimal string.
54
54
  shares: string;
55
55
  }
56
+
57
+ /// `vault_distribute` — a follower deposits USD into a vault and receives shares
58
+ /// at the current NAV (subject to the per-vault withdrawal lock). Mirrors the
59
+ /// node's `core_state` `VaultDistributeParams`; the action envelope wraps this
60
+ /// under the key **`params`**.
61
+ ///
62
+ /// **Trap:** the deposit-amount field is named **`pnl`** (a legacy name on the
63
+ /// node), NOT `amount`/`deposit`. It is a positive USD amount encoded as a
64
+ /// decimal string (the SDK's decimal-on-the-wire convention, matching
65
+ /// `vault_transfer` / `vault_withdraw`).
66
+ ///
67
+ /// Forward-compat: the node currently answers this tag with `UnsupportedAction`
68
+ /// on the public `/exchange` path; the SDK emits the byte-correct shape the core
69
+ /// handler will accept once the bridge lands.
70
+ export interface VaultDistribute {
71
+ /// Target vault id (`u64`). Serializes as a bare JSON number.
72
+ vault_id: number;
73
+ /// Deposit amount in USD as a positive decimal string. Node field name is
74
+ /// `pnl` (legacy) — do NOT rename.
75
+ pnl: string;
76
+ }