@switch-win/sdk 1.0.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.
- package/README.md +950 -0
- package/abi/SwitchLimitOrderABI.json +1296 -0
- package/abi/SwitchRouterABI.json +954 -0
- package/package.json +41 -0
- package/src/constants.ts +238 -0
- package/src/index.ts +110 -0
- package/src/limit-orders.ts +435 -0
- package/src/types.ts +423 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch Limit Orders (V2) — Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Provides a complete toolkit for creating, signing, submitting, querying,
|
|
5
|
+
* and cancelling EIP-712 signed limit orders on PulseChain.
|
|
6
|
+
*
|
|
7
|
+
* ## How it works
|
|
8
|
+
*
|
|
9
|
+
* 1. **Build** order parameters with `buildLimitOrder()`
|
|
10
|
+
* 2. **Sign** via EIP-712 with your wallet (ethers.js `signTypedData`)
|
|
11
|
+
* 3. **Submit** the signed order to the Switch backend with `submitLimitOrder()`
|
|
12
|
+
* 4. The Switch filler bot monitors active orders and fills them when profitable
|
|
13
|
+
* 5. **Cancel** an order on-chain via `invalidateNonce()` + notify backend with `cancelLimitOrder()`
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { buildLimitOrder, submitLimitOrder, fetchLimitOrders } from "@switch-win/sdk/limit-orders";
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type {
|
|
22
|
+
LimitOrderParams,
|
|
23
|
+
SignedLimitOrder,
|
|
24
|
+
CreateLimitOrderResponse,
|
|
25
|
+
CancelLimitOrderResponse,
|
|
26
|
+
ListLimitOrdersResponse,
|
|
27
|
+
LimitOrderRecord,
|
|
28
|
+
LimitOrderPair,
|
|
29
|
+
LimitOrderStats,
|
|
30
|
+
LimitOrderStatus,
|
|
31
|
+
ErrorResponse,
|
|
32
|
+
} from "./types.js";
|
|
33
|
+
|
|
34
|
+
import {
|
|
35
|
+
LIMIT_ORDERS_ENDPOINT,
|
|
36
|
+
LIMIT_ORDER_PAIRS_ENDPOINT,
|
|
37
|
+
LIMIT_ORDER_STATS_ENDPOINT,
|
|
38
|
+
LIMIT_ORDER_EIP712_DOMAIN,
|
|
39
|
+
LIMIT_ORDER_EIP712_TYPES,
|
|
40
|
+
SWITCH_LIMIT_ORDER,
|
|
41
|
+
SWITCH_ROUTER,
|
|
42
|
+
SWITCH_PLS_FLOW,
|
|
43
|
+
WPLS,
|
|
44
|
+
} from "./constants.js";
|
|
45
|
+
|
|
46
|
+
// ── Re-export EIP-712 constants for convenience ─────────────────────────────
|
|
47
|
+
|
|
48
|
+
export { LIMIT_ORDER_EIP712_DOMAIN, LIMIT_ORDER_EIP712_TYPES } from "./constants.js";
|
|
49
|
+
|
|
50
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
51
|
+
// Order Construction
|
|
52
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
53
|
+
|
|
54
|
+
/** Options for building a limit order */
|
|
55
|
+
export interface BuildLimitOrderOptions {
|
|
56
|
+
/** Maker (signer) address */
|
|
57
|
+
maker: string;
|
|
58
|
+
/** Input token address (token being sold) */
|
|
59
|
+
tokenIn: string;
|
|
60
|
+
/** Output token address (token being bought) */
|
|
61
|
+
tokenOut: string;
|
|
62
|
+
/** Amount of tokenIn to sell (wei string) */
|
|
63
|
+
amountIn: string;
|
|
64
|
+
/** Minimum amount of tokenOut to accept (wei string) */
|
|
65
|
+
minAmountOut: string;
|
|
66
|
+
/**
|
|
67
|
+
* Order expiry as a Unix timestamp. Defaults to `0` (no expiry).
|
|
68
|
+
* Tip: use `Math.floor(Date.now() / 1000) + 86400` for 24-hour expiry.
|
|
69
|
+
*/
|
|
70
|
+
deadline?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Unique nonce. Defaults to `Date.now()` (milliseconds) which is
|
|
73
|
+
* practically unique for a single maker. You can also use a random integer.
|
|
74
|
+
*/
|
|
75
|
+
nonce?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Fee mode — `true` to take fee from output, `false` from input. Default `false`.
|
|
78
|
+
*
|
|
79
|
+
* This choice is **permanent once signed** and has two major effects:
|
|
80
|
+
*
|
|
81
|
+
* ### 1. Determines the approval target
|
|
82
|
+
*
|
|
83
|
+
* | `feeOnOutput` | Maker must approve | Helper |
|
|
84
|
+
* |---|---|---|
|
|
85
|
+
* | `false` (default) | **SwitchLimitOrder** | `getApprovalTarget()` |
|
|
86
|
+
* | `true` | **SwitchRouter** | `getRouterApprovalTarget()` |
|
|
87
|
+
*
|
|
88
|
+
* ### 2. Constrains how operators (fillers) can take profit
|
|
89
|
+
*
|
|
90
|
+
* When `feeOnOutput=false`, the LO contract holds all input tokens
|
|
91
|
+
* after pulling them from the maker. Operators can freely choose to
|
|
92
|
+
* take their profit from either the input side or the output side.
|
|
93
|
+
*
|
|
94
|
+
* When `feeOnOutput=true`, the Router pulls tokens directly from the
|
|
95
|
+
* maker. If an operator also wants to take excess *input* tokens,
|
|
96
|
+
* the LO contract would need a **second** approval (from the maker
|
|
97
|
+
* to the LO contract) — which the maker typically hasn't granted.
|
|
98
|
+
* This means operators are effectively limited to taking profit
|
|
99
|
+
* from the output side only. The order is still fully fillable,
|
|
100
|
+
* but operators have less flexibility. In low-liquidity or
|
|
101
|
+
* tight-margin situations, this could reduce the chance of a fill.
|
|
102
|
+
*
|
|
103
|
+
* ### 3. Tax (fee-on-transfer) token guidelines
|
|
104
|
+
*
|
|
105
|
+
* - **Tax input token** → set `feeOnOutput: true`
|
|
106
|
+
* (Router sends tokens directly from maker to pool — one transfer,
|
|
107
|
+
* one tax. Avoids the double sell-tax of maker → LO → pool.)
|
|
108
|
+
* - **Tax output token** → set `feeOnOutput: false` (default)
|
|
109
|
+
* (Output goes directly to recipient in one transfer.)
|
|
110
|
+
* - **Both tokens tax** → not supported (frontend blocks this)
|
|
111
|
+
*
|
|
112
|
+
* **Bottom line:** Use `feeOnOutput: false` (default) unless the input
|
|
113
|
+
* token is a tax token. This gives operators maximum flexibility and
|
|
114
|
+
* the best chance of your order being filled.
|
|
115
|
+
*/
|
|
116
|
+
feeOnOutput?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Recipient address for the output tokens. Defaults to the maker address.
|
|
119
|
+
* Set to a different address to send output to another wallet.
|
|
120
|
+
*/
|
|
121
|
+
recipient?: string;
|
|
122
|
+
/**
|
|
123
|
+
* If `true` and tokenOut is WPLS, the contract unwraps to native PLS
|
|
124
|
+
* before sending to the recipient. Default `false`.
|
|
125
|
+
*/
|
|
126
|
+
unwrapOutput?: boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Build a `LimitOrderParams` object ready for EIP-712 signing.
|
|
131
|
+
*
|
|
132
|
+
* @param options - Order parameters
|
|
133
|
+
* @returns A fully-populated `LimitOrderParams` object
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const order = buildLimitOrder({
|
|
138
|
+
* maker: "0xYourAddress",
|
|
139
|
+
* tokenIn: WPLS,
|
|
140
|
+
* tokenOut: "0xPLSXAddress",
|
|
141
|
+
* amountIn: ethers.parseUnits("1000", 18).toString(),
|
|
142
|
+
* minAmountOut: ethers.parseUnits("500000", 18).toString(),
|
|
143
|
+
* });
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export function buildLimitOrder(options: BuildLimitOrderOptions): LimitOrderParams {
|
|
147
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
maker: options.maker,
|
|
151
|
+
tokenIn: options.tokenIn,
|
|
152
|
+
tokenOut: options.tokenOut,
|
|
153
|
+
amountIn: options.amountIn,
|
|
154
|
+
minAmountOut: options.minAmountOut,
|
|
155
|
+
deadline: options.deadline ?? 0,
|
|
156
|
+
nonce: options.nonce ?? Date.now(),
|
|
157
|
+
feeOnOutput: options.feeOnOutput ?? false,
|
|
158
|
+
recipient: options.recipient ?? options.maker,
|
|
159
|
+
unwrapOutput: options.unwrapOutput ?? false,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get the EIP-712 domain and types needed for signing a limit order.
|
|
165
|
+
*
|
|
166
|
+
* Pass the returned values directly to your wallet's `signTypedData` method.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* // ethers.js v6
|
|
171
|
+
* const { domain, types } = getEIP712SigningParams();
|
|
172
|
+
* const signature = await signer.signTypedData(domain, types, order);
|
|
173
|
+
*
|
|
174
|
+
* // ethers.js v5
|
|
175
|
+
* const signature = await signer._signTypedData(domain, types, order);
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export function getEIP712SigningParams() {
|
|
179
|
+
return {
|
|
180
|
+
domain: LIMIT_ORDER_EIP712_DOMAIN,
|
|
181
|
+
types: LIMIT_ORDER_EIP712_TYPES,
|
|
182
|
+
} as const;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get the approval target for `feeOnOutput: false` orders (the default).
|
|
187
|
+
*
|
|
188
|
+
* When `feeOnOutput` is `false`, the **SwitchLimitOrder** contract pulls
|
|
189
|
+
* tokens from the maker via `safeTransferFrom`, then forwards them to the
|
|
190
|
+
* router internally. The maker must `approve(SWITCH_LIMIT_ORDER, amountIn)`.
|
|
191
|
+
*
|
|
192
|
+
* For `feeOnOutput: true` orders, use {@link getRouterApprovalTarget} instead.
|
|
193
|
+
*
|
|
194
|
+
* @returns The SwitchLimitOrder contract address
|
|
195
|
+
*/
|
|
196
|
+
export function getApprovalTarget(): string {
|
|
197
|
+
return SWITCH_LIMIT_ORDER;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get the approval target for `feeOnOutput: true` orders.
|
|
202
|
+
*
|
|
203
|
+
* When `feeOnOutput` is `true`, the **SwitchRouter** pulls tokens directly
|
|
204
|
+
* from the maker via `goSwitchFrom` (one transfer, one tax — ideal for tax
|
|
205
|
+
* input tokens). The maker must `approve(SWITCH_ROUTER, amountIn)`.
|
|
206
|
+
*
|
|
207
|
+
* For `feeOnOutput: false` orders (default), use {@link getApprovalTarget} instead.
|
|
208
|
+
*
|
|
209
|
+
* @returns The SwitchRouter contract address
|
|
210
|
+
*/
|
|
211
|
+
export function getRouterApprovalTarget(): string {
|
|
212
|
+
return SWITCH_ROUTER;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Determine whether `unwrapOutput` should be set for a given output token.
|
|
217
|
+
*
|
|
218
|
+
* Returns `true` only if `tokenOut` is WPLS (the output will be unwrapped
|
|
219
|
+
* to native PLS by the contract).
|
|
220
|
+
*/
|
|
221
|
+
export function shouldUnwrapOutput(tokenOut: string): boolean {
|
|
222
|
+
return tokenOut.toLowerCase() === WPLS.toLowerCase();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
226
|
+
// PLSFlow (Native PLS Limit Orders)
|
|
227
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get the SwitchPLSFlow contract address.
|
|
231
|
+
*
|
|
232
|
+
* Use this contract to create native PLS limit orders (sell PLS for any token)
|
|
233
|
+
* in a single transaction — no EIP-712 signing required.
|
|
234
|
+
*
|
|
235
|
+
* @returns The SwitchPLSFlow contract address
|
|
236
|
+
*/
|
|
237
|
+
export function getPLSFlowAddress(): string {
|
|
238
|
+
return SWITCH_PLS_FLOW;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Check if the input token is native PLS (should use PLSFlow instead of EIP-712).
|
|
243
|
+
*
|
|
244
|
+
* When the user wants to sell native PLS (not WPLS), they should use the
|
|
245
|
+
* PLSFlow contract instead of the standard EIP-712 signing flow.
|
|
246
|
+
*
|
|
247
|
+
* @param tokenIn - The input token address
|
|
248
|
+
* @returns `true` if tokenIn is the native PLS sentinel address
|
|
249
|
+
*/
|
|
250
|
+
export function isNativePLS(tokenIn: string): boolean {
|
|
251
|
+
const NATIVE_SENTINEL = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
252
|
+
return tokenIn.toLowerCase() === NATIVE_SENTINEL.toLowerCase();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
256
|
+
// API Helpers
|
|
257
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Submit a signed limit order to the Switch backend.
|
|
261
|
+
*
|
|
262
|
+
* The backend verifies the EIP-712 signature and stores the order. No gas
|
|
263
|
+
* is required — this is an off-chain operation.
|
|
264
|
+
*
|
|
265
|
+
* **⚠️ CRITICAL:** For standard ERC-20 orders, the EIP-712 signature is
|
|
266
|
+
* purely off-chain — nothing is recorded on-chain until the bot fills it.
|
|
267
|
+
* If this POST fails or never fires (e.g. user closes their browser after
|
|
268
|
+
* signing), the **order is permanently lost**. Your integration should:
|
|
269
|
+
*
|
|
270
|
+
* 1. Call `submitLimitOrder()` **immediately** after the user signs.
|
|
271
|
+
* 2. **Await** the response and verify `success: true` before showing
|
|
272
|
+
* the order as "created" in your UI.
|
|
273
|
+
* 3. If the POST fails, **retry** automatically (the backend is
|
|
274
|
+
* idempotent on `maker + nonce`, so retries are safe).
|
|
275
|
+
* 4. Do **not** navigate away or close the signing flow until the
|
|
276
|
+
* backend confirms the order.
|
|
277
|
+
*
|
|
278
|
+
* PLSFlow (native PLS) orders are an exception — they are recorded
|
|
279
|
+
* on-chain first, so the backend can discover them via event indexing
|
|
280
|
+
* even if the POST never arrives.
|
|
281
|
+
*
|
|
282
|
+
* @param signedOrder - Order parameters + EIP-712 signature
|
|
283
|
+
* @returns The created order record, or an error
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```ts
|
|
287
|
+
* const order = buildLimitOrder({ ... });
|
|
288
|
+
* const signature = await signer.signTypedData(domain, types, order);
|
|
289
|
+
* const result = await submitLimitOrder({ ...order, signature });
|
|
290
|
+
*
|
|
291
|
+
* if ("error" in result) {
|
|
292
|
+
* console.error(result.error);
|
|
293
|
+
* } else {
|
|
294
|
+
* console.log("Order created:", result.order.id);
|
|
295
|
+
* }
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
export async function submitLimitOrder(
|
|
299
|
+
signedOrder: SignedLimitOrder,
|
|
300
|
+
): Promise<CreateLimitOrderResponse | ErrorResponse> {
|
|
301
|
+
const res = await fetch(LIMIT_ORDERS_ENDPOINT, {
|
|
302
|
+
method: "POST",
|
|
303
|
+
headers: { "Content-Type": "application/json" },
|
|
304
|
+
body: JSON.stringify(signedOrder),
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
return res.json() as Promise<CreateLimitOrderResponse | ErrorResponse>;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Cancel a limit order on the Switch backend (marks it CANCELLED in the DB).
|
|
312
|
+
*
|
|
313
|
+
* **Important:** This only removes the order from the backend orderbook. To
|
|
314
|
+
* prevent the order from being filled on-chain, you MUST also call
|
|
315
|
+
* `invalidateNonce(nonce)` on the SwitchLimitOrder contract. See the
|
|
316
|
+
* cancellation guide in the README.
|
|
317
|
+
*
|
|
318
|
+
* @param maker - Maker address
|
|
319
|
+
* @param nonce - Nonce of the order to cancel
|
|
320
|
+
* @returns Success confirmation or error
|
|
321
|
+
*/
|
|
322
|
+
export async function cancelLimitOrder(
|
|
323
|
+
maker: string,
|
|
324
|
+
nonce: number,
|
|
325
|
+
): Promise<CancelLimitOrderResponse | ErrorResponse> {
|
|
326
|
+
const res = await fetch(LIMIT_ORDERS_ENDPOINT, {
|
|
327
|
+
method: "DELETE",
|
|
328
|
+
headers: { "Content-Type": "application/json" },
|
|
329
|
+
body: JSON.stringify({ maker, nonce }),
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return res.json() as Promise<CancelLimitOrderResponse | ErrorResponse>;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** Filter options for listing limit orders */
|
|
336
|
+
export interface ListLimitOrdersOptions {
|
|
337
|
+
/** Filter by order status. Default: `"ACTIVE"` */
|
|
338
|
+
status?: LimitOrderStatus;
|
|
339
|
+
/** Filter by maker address */
|
|
340
|
+
maker?: string;
|
|
341
|
+
/**
|
|
342
|
+
* Filter by owner address. Matches orders where the address is either
|
|
343
|
+
* the `maker` or `recipient` field. Useful for native-PLS (PLSFlow) orders
|
|
344
|
+
* where the maker is the PLSFlow contract but the user is the recipient.
|
|
345
|
+
*/
|
|
346
|
+
owner?: string;
|
|
347
|
+
/** Filter by input token address */
|
|
348
|
+
tokenIn?: string;
|
|
349
|
+
/** Filter by output token address */
|
|
350
|
+
tokenOut?: string;
|
|
351
|
+
/** Filter by pair key (`tokenIn:tokenOut`, lowercased) */
|
|
352
|
+
pair?: string;
|
|
353
|
+
/** Page size (1–500). Default: `100` */
|
|
354
|
+
limit?: number;
|
|
355
|
+
/** Page offset. Default: `0` */
|
|
356
|
+
offset?: number;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Fetch limit orders from the Switch backend with optional filters.
|
|
361
|
+
*
|
|
362
|
+
* @param options - Query filters (all optional)
|
|
363
|
+
* @returns Paginated list of orders
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```ts
|
|
367
|
+
* // All active orders for a specific maker
|
|
368
|
+
* const { orders, total } = await fetchLimitOrders({
|
|
369
|
+
* maker: "0xYourAddress",
|
|
370
|
+
* status: "ACTIVE",
|
|
371
|
+
* });
|
|
372
|
+
*
|
|
373
|
+
* // All filled orders for a token pair
|
|
374
|
+
* const filled = await fetchLimitOrders({
|
|
375
|
+
* tokenIn: WPLS,
|
|
376
|
+
* tokenOut: "0xPLSXAddress",
|
|
377
|
+
* status: "FILLED",
|
|
378
|
+
* });
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
export async function fetchLimitOrders(
|
|
382
|
+
options: ListLimitOrdersOptions = {},
|
|
383
|
+
): Promise<ListLimitOrdersResponse> {
|
|
384
|
+
const params = new URLSearchParams();
|
|
385
|
+
if (options.status) params.set("status", options.status);
|
|
386
|
+
if (options.maker) params.set("maker", options.maker);
|
|
387
|
+
if (options.owner) params.set("owner", options.owner);
|
|
388
|
+
if (options.tokenIn) params.set("tokenIn", options.tokenIn);
|
|
389
|
+
if (options.tokenOut) params.set("tokenOut", options.tokenOut);
|
|
390
|
+
if (options.pair) params.set("pair", options.pair);
|
|
391
|
+
if (options.limit != null) params.set("limit", String(options.limit));
|
|
392
|
+
if (options.offset != null) params.set("offset", String(options.offset));
|
|
393
|
+
|
|
394
|
+
const url = params.toString()
|
|
395
|
+
? `${LIMIT_ORDERS_ENDPOINT}?${params}`
|
|
396
|
+
: LIMIT_ORDERS_ENDPOINT;
|
|
397
|
+
|
|
398
|
+
const res = await fetch(url);
|
|
399
|
+
return res.json() as Promise<ListLimitOrdersResponse>;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Fetch a single limit order by maker address and nonce.
|
|
404
|
+
*
|
|
405
|
+
* @param maker - Maker address
|
|
406
|
+
* @param nonce - Order nonce
|
|
407
|
+
* @returns The order record, or an error if not found
|
|
408
|
+
*/
|
|
409
|
+
export async function fetchLimitOrder(
|
|
410
|
+
maker: string,
|
|
411
|
+
nonce: number,
|
|
412
|
+
): Promise<LimitOrderRecord | ErrorResponse> {
|
|
413
|
+
const res = await fetch(`${LIMIT_ORDERS_ENDPOINT}/${maker}/${nonce}`);
|
|
414
|
+
return res.json() as Promise<LimitOrderRecord | ErrorResponse>;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Fetch active trading pairs with order counts.
|
|
419
|
+
*
|
|
420
|
+
* Useful for displaying which token pairs have open limit orders.
|
|
421
|
+
*/
|
|
422
|
+
export async function fetchLimitOrderPairs(): Promise<LimitOrderPair[]> {
|
|
423
|
+
const res = await fetch(LIMIT_ORDER_PAIRS_ENDPOINT);
|
|
424
|
+
return res.json() as Promise<LimitOrderPair[]>;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Fetch summary statistics for all limit orders.
|
|
429
|
+
*
|
|
430
|
+
* Returns counts of active, filled, cancelled, and expired orders.
|
|
431
|
+
*/
|
|
432
|
+
export async function fetchLimitOrderStats(): Promise<LimitOrderStats> {
|
|
433
|
+
const res = await fetch(LIMIT_ORDER_STATS_ENDPOINT);
|
|
434
|
+
return res.json() as Promise<LimitOrderStats>;
|
|
435
|
+
}
|