@splitmarkets/sdk 0.2.2 → 0.2.3

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 (2) hide show
  1. package/dist/widget.js +529 -119
  2. package/package.json +1 -1
package/dist/widget.js CHANGED
@@ -1,6 +1,6 @@
1
- import { getMarkets, getPositionGasless, getPosition, deriveTradingAccount, buyGasless, buy, closeGasless, close } from './chunk-FDWH3X5N.js';
2
- import { useState, useId, useMemo, useEffect, useCallback } from 'react';
3
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { getMarkets, getPositionGasless, getPosition, deriveTradingAccount, closeGasless, buyGasless, buy, close } from './chunk-FDWH3X5N.js';
2
+ import { useState, useCallback, useId, useMemo, useEffect } from 'react';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  var THEMES = {
6
6
  dark: {
@@ -23,6 +23,8 @@ var THEMES = {
23
23
  }
24
24
  };
25
25
  var toLen = (v) => v === void 0 ? void 0 : typeof v === "number" ? `${v}px` : v;
26
+ var fmtUsd = (n, max = 0) => n.toLocaleString(void 0, { maximumFractionDigits: max, minimumFractionDigits: 0 });
27
+ var posKey = (side, seriesId) => `${side}:${seriesId}`;
26
28
  function SplitTradeWidget({
27
29
  walletClient,
28
30
  account,
@@ -35,12 +37,25 @@ function SplitTradeWidget({
35
37
  const gasless = mode === "gasless";
36
38
  const [side, setSide] = useState("long");
37
39
  const [markets, setMarkets] = useState([]);
40
+ const [loadingMarkets, setLoadingMarkets] = useState(true);
38
41
  const [picked, setPicked] = useState(null);
39
42
  const [amount, setAmount] = useState("5");
40
43
  const [position, setPosition] = useState(null);
44
+ const [paidUsd, setPaidUsd] = useState(null);
41
45
  const [status, setStatus] = useState("");
46
+ const [statusKind, setStatusKind] = useState("info");
42
47
  const [busy, setBusy] = useState(false);
43
48
  const [trading, setTrading] = useState(null);
49
+ const [openPositions, setOpenPositions] = useState([]);
50
+ const [loadingPositions, setLoadingPositions] = useState(false);
51
+ const [positionsError, setPositionsError] = useState(null);
52
+ const [positionsLoaded, setPositionsLoaded] = useState(false);
53
+ const [sellingKey, setSellingKey] = useState(null);
54
+ const [costBasis, setCostBasis] = useState({});
55
+ const note = useCallback((msg, kind = "info") => {
56
+ setStatus(msg);
57
+ setStatusKind(kind);
58
+ }, []);
44
59
  const scope = useId().replace(/[^a-zA-Z0-9_-]/g, "");
45
60
  const rootClass = `swt-${scope}`;
46
61
  const vars = useMemo(() => {
@@ -68,176 +83,460 @@ function SplitTradeWidget({
68
83
  let alive = true;
69
84
  setMarkets([]);
70
85
  setPicked(null);
86
+ setLoadingMarkets(true);
71
87
  getMarkets(chain, side).then((m) => {
72
88
  if (!alive) return;
73
89
  setMarkets(m);
74
90
  if (m.length) setPicked(m[0].seriesId);
75
- }).catch((e) => alive && setStatus(`Couldn't load markets: ${e.message}`));
91
+ }).catch((e) => alive && note(`Couldn't load markets: ${e.message}`, "err")).finally(() => alive && setLoadingMarkets(false));
76
92
  return () => {
77
93
  alive = false;
78
94
  };
79
- }, [chain, side]);
80
- const refreshPosition = useCallback(async () => {
81
- if (!account || picked === null) {
82
- setPosition(null);
83
- return;
84
- }
85
- try {
86
- if (gasless) {
87
- if (!trading) {
88
- setPosition(null);
89
- return;
95
+ }, [chain, side, note]);
96
+ const refreshPosition = useCallback(
97
+ async (tradingOverride) => {
98
+ if (!account || picked === null) {
99
+ setPosition(null);
100
+ return;
101
+ }
102
+ try {
103
+ if (gasless) {
104
+ const t = tradingOverride ?? trading;
105
+ if (!t) {
106
+ setPosition(null);
107
+ return;
108
+ }
109
+ const p = await getPositionGasless({ chain, side, seriesId: picked, account, walletClient, trading: t });
110
+ setPosition({ qN: p.qN, markUsd: p.markUsd, intrinsicUsd: p.intrinsicUsd });
111
+ } else {
112
+ setPosition(await getPosition({ chain, side, seriesId: picked, account }));
90
113
  }
91
- const p = await getPositionGasless({ chain, side, seriesId: picked, account, walletClient, trading });
92
- setPosition({ qN: p.qN, markUsd: p.markUsd, intrinsicUsd: p.intrinsicUsd });
93
- } else {
94
- setPosition(await getPosition({ chain, side, seriesId: picked, account }));
114
+ } catch {
115
+ setPosition(null);
95
116
  }
96
- } catch {
97
- setPosition(null);
98
- }
99
- }, [account, chain, side, picked, gasless, trading, walletClient]);
117
+ },
118
+ [account, chain, side, picked, gasless, trading, walletClient]
119
+ );
100
120
  useEffect(() => {
101
121
  refreshPosition();
102
122
  }, [refreshPosition]);
123
+ const loadPositions = useCallback(
124
+ async (tradingOverride) => {
125
+ if (!gasless) return;
126
+ const t = tradingOverride ?? trading;
127
+ if (!t || !account || !walletClient) return;
128
+ setLoadingPositions(true);
129
+ setPositionsError(null);
130
+ try {
131
+ const [longMarkets, shortMarkets] = await Promise.all([
132
+ getMarkets(chain, "long").catch(() => []),
133
+ getMarkets(chain, "short").catch(() => [])
134
+ ]);
135
+ const entries = [
136
+ ...longMarkets.map((m) => ({ side: "long", market: m })),
137
+ ...shortMarkets.map((m) => ({ side: "short", market: m }))
138
+ ];
139
+ const results = await Promise.all(
140
+ entries.map(async ({ side: s, market: m }) => {
141
+ try {
142
+ const p = await getPositionGasless({
143
+ chain,
144
+ side: s,
145
+ seriesId: m.seriesId,
146
+ account,
147
+ walletClient,
148
+ trading: t
149
+ });
150
+ if (!(p.qN > 0)) return null;
151
+ return {
152
+ side: s,
153
+ seriesId: m.seriesId,
154
+ leverage: m.leverage,
155
+ strike: m.strike,
156
+ qN: p.qN,
157
+ markUsd: p.markUsd,
158
+ intrinsicUsd: p.intrinsicUsd
159
+ };
160
+ } catch {
161
+ return null;
162
+ }
163
+ })
164
+ );
165
+ const open = results.filter((p) => p !== null);
166
+ open.sort((a, b) => b.markUsd - a.markUsd);
167
+ setOpenPositions(open);
168
+ setPositionsLoaded(true);
169
+ } catch (e) {
170
+ setPositionsError(errMsg(e));
171
+ } finally {
172
+ setLoadingPositions(false);
173
+ }
174
+ },
175
+ [gasless, trading, account, walletClient, chain]
176
+ );
177
+ const onLoadPositions = useCallback(async () => {
178
+ if (!walletClient || !account) {
179
+ note("Connect a wallet first.", "err");
180
+ return;
181
+ }
182
+ setLoadingPositions(true);
183
+ setPositionsError(null);
184
+ try {
185
+ note("Confirm one signature to load your Split positions\u2026");
186
+ const t = trading ?? await deriveTradingAccount(walletClient, account, chain);
187
+ if (!trading) setTrading(t);
188
+ await loadPositions(t);
189
+ note("");
190
+ } catch (e) {
191
+ setPositionsError(errMsg(e));
192
+ note(`Couldn't load positions: ${errMsg(e)}`, "err");
193
+ setLoadingPositions(false);
194
+ }
195
+ }, [walletClient, account, chain, trading, loadPositions, note]);
196
+ const onSell = useCallback(
197
+ async (p) => {
198
+ if (!walletClient || !account) return;
199
+ const key = posKey(p.side, p.seriesId);
200
+ setSellingKey(key);
201
+ try {
202
+ const t = trading ?? await deriveTradingAccount(walletClient, account, chain);
203
+ if (!trading) setTrading(t);
204
+ note(`Closing your ${p.side === "long" ? "Long" : "Short"} position\u2026`);
205
+ const r = await closeGasless({ chain, side: p.side, seriesId: p.seriesId, walletClient, account, trading: t });
206
+ note(`Closed ${p.side === "long" ? "Long" : "Short"} \xB7 tx ${r.txHash.slice(0, 10)}\u2026`, "ok");
207
+ setCostBasis((prev) => {
208
+ const next = { ...prev };
209
+ delete next[key];
210
+ return next;
211
+ });
212
+ if (p.side === side && p.seriesId === picked) setPaidUsd(null);
213
+ await loadPositions(t);
214
+ await refreshPosition(t);
215
+ } catch (e) {
216
+ note(`Close failed: ${errMsg(e)}`, "err");
217
+ } finally {
218
+ setSellingKey(null);
219
+ }
220
+ },
221
+ [walletClient, account, chain, trading, side, picked, loadPositions, refreshPosition, note]
222
+ );
103
223
  const onBuy = useCallback(async () => {
104
224
  if (!walletClient || !account || picked === null) {
105
- setStatus("Connect a wallet first.");
225
+ note("Connect a wallet first.", "err");
106
226
  return;
107
227
  }
108
228
  const usd = Number(amount);
109
229
  if (!(usd > 0)) {
110
- setStatus("Enter a dollar amount > 0.");
230
+ note("Enter a dollar amount greater than 0.", "err");
111
231
  return;
112
232
  }
113
233
  const m = markets.find((x) => x.seriesId === picked);
114
234
  if (!m || !(m.premium > 0)) {
115
- setStatus("Market not ready \u2014 try again.");
235
+ note("Market not ready \u2014 try again.", "err");
116
236
  return;
117
237
  }
118
238
  const qN = usd / m.premium;
119
239
  setBusy(true);
120
240
  try {
121
241
  if (gasless) {
122
- setStatus("Confirm one signature\u2026");
242
+ note("Confirm one signature \u2014 no gas, can't be liquidated\u2026");
123
243
  const t = trading ?? await deriveTradingAccount(walletClient, account, chain);
124
244
  if (!trading) setTrading(t);
125
245
  const r = await buyGasless({ chain, side, seriesId: picked, qN, walletClient, account, trading: t });
126
- setStatus(`Bought $${usd} of ${side}. tx ${r.txHash.slice(0, 10)}\u2026`);
246
+ note(`Bought $${fmtUsd(usd)} ${side === "long" ? "Long" : "Short"} \xB7 tx ${r.txHash.slice(0, 10)}\u2026`, "ok");
247
+ setPaidUsd(usd);
248
+ setCostBasis((prev) => ({ ...prev, [posKey(side, picked)]: usd }));
249
+ await refreshPosition(t);
250
+ await loadPositions(t);
127
251
  } else {
128
- setStatus("Confirm in your wallet (approve, then buy)\u2026");
252
+ note("Confirm in your wallet (approve, then buy)\u2026");
129
253
  const r = await buy({ chain, side, seriesId: picked, qN, walletClient, account });
130
- setStatus(`Bought $${usd} of ${side}. tx ${r.txHash.slice(0, 10)}\u2026`);
254
+ note(`Bought $${fmtUsd(usd)} ${side === "long" ? "Long" : "Short"} \xB7 tx ${r.txHash.slice(0, 10)}\u2026`, "ok");
255
+ setPaidUsd(usd);
256
+ await refreshPosition();
131
257
  }
132
- await refreshPosition();
133
258
  } catch (e) {
134
- setStatus(`Buy failed: ${errMsg(e)}`);
259
+ note(`Buy failed: ${errMsg(e)}`, "err");
135
260
  } finally {
136
261
  setBusy(false);
137
262
  }
138
- }, [walletClient, account, chain, side, picked, amount, refreshPosition, gasless, trading]);
263
+ }, [walletClient, account, chain, side, picked, amount, markets, refreshPosition, loadPositions, gasless, trading, note]);
139
264
  const onClose = useCallback(async () => {
140
265
  if (!walletClient || !account || picked === null) return;
141
266
  setBusy(true);
142
267
  try {
143
268
  if (gasless) {
144
- setStatus("Closing\u2026");
269
+ note("Closing your position\u2026");
145
270
  const t = trading ?? await deriveTradingAccount(walletClient, account, chain);
146
271
  if (!trading) setTrading(t);
147
272
  const r = await closeGasless({ chain, side, seriesId: picked, walletClient, account, trading: t });
148
- setStatus(`Closed. tx ${r.txHash.slice(0, 10)}\u2026`);
273
+ note(`Closed \xB7 tx ${r.txHash.slice(0, 10)}\u2026`, "ok");
274
+ setPaidUsd(null);
275
+ setCostBasis((prev) => {
276
+ const next = { ...prev };
277
+ delete next[posKey(side, picked)];
278
+ return next;
279
+ });
280
+ await refreshPosition(t);
281
+ await loadPositions(t);
149
282
  } else {
150
- setStatus("Confirm in your wallet (approve, then close)\u2026");
283
+ note("Confirm in your wallet (approve, then close)\u2026");
151
284
  const r = await close({ chain, side, seriesId: picked, walletClient, account });
152
- setStatus(`Closed ${r.qN} contracts. tx ${r.txHash.slice(0, 10)}\u2026`);
285
+ note(`Closed ${r.qN} contracts \xB7 tx ${r.txHash.slice(0, 10)}\u2026`, "ok");
286
+ setPaidUsd(null);
287
+ await refreshPosition();
153
288
  }
154
- await refreshPosition();
155
289
  } catch (e) {
156
- setStatus(`Close failed: ${errMsg(e)}`);
290
+ note(`Close failed: ${errMsg(e)}`, "err");
157
291
  } finally {
158
292
  setBusy(false);
159
293
  }
160
- }, [walletClient, account, chain, side, picked, refreshPosition, gasless, trading]);
294
+ }, [walletClient, account, chain, side, picked, refreshPosition, loadPositions, gasless, trading, note]);
161
295
  const hasPosition = !!position && position.qN > 0;
296
+ const pickedMarket = markets.find((x) => x.seriesId === picked) ?? null;
297
+ const pnl = hasPosition && paidUsd !== null ? position.markUsd - paidUsd : null;
298
+ const pnlPct = pnl !== null && paidUsd ? pnl / paidUsd * 100 : null;
299
+ const pnlUp = pnl !== null && pnl >= 0;
300
+ const breakevenFor = (m) => side === "long" ? m.strike + m.premium : m.strike - m.premium;
301
+ const canBuy = !busy && picked !== null && !!walletClient && !!account && Number(amount) > 0;
302
+ const canOfferLoad = gasless && !!walletClient && !!account && !trading && !positionsLoaded;
303
+ const showPositionsList = gasless && (!!trading || positionsLoaded);
162
304
  return /* @__PURE__ */ jsxs("div", { className: [rootClass, className].filter(Boolean).join(" "), style: vars, children: [
163
305
  /* @__PURE__ */ jsx("style", { children: css(rootClass) }),
164
306
  /* @__PURE__ */ jsxs("div", { className: "swt-card", children: [
165
307
  /* @__PURE__ */ jsxs("div", { className: "swt-head", children: [
166
- /* @__PURE__ */ jsx("strong", { children: "Trade leverage on Split" }),
167
- /* @__PURE__ */ jsx("span", { className: "swt-tag", children: "can't be liquidated \xB7 max loss = premium" })
308
+ /* @__PURE__ */ jsxs("div", { className: "swt-brand", children: [
309
+ /* @__PURE__ */ jsx("span", { className: "swt-logo", "aria-hidden": "true", children: "\u25C8" }),
310
+ /* @__PURE__ */ jsx("strong", { children: "Trade leverage on Split" })
311
+ ] }),
312
+ /* @__PURE__ */ jsxs("span", { className: "swt-tag", children: [
313
+ /* @__PURE__ */ jsx("span", { className: "swt-dot", "aria-hidden": "true" }),
314
+ "Can't be liquidated \xB7 max loss = premium"
315
+ ] })
168
316
  ] }),
169
- /* @__PURE__ */ jsx("div", { className: "swt-row", children: ["long", "short"].map((s) => /* @__PURE__ */ jsx(
170
- "button",
171
- {
172
- type: "button",
173
- onClick: () => setSide(s),
174
- className: `swt-toggle${side === s ? " is-on" : ""}`,
175
- children: s === "long" ? "Long (ETH up)" : "Short (ETH down)"
176
- },
177
- s
178
- )) }),
179
- /* @__PURE__ */ jsxs("div", { className: "swt-tiles", children: [
180
- markets.length === 0 && /* @__PURE__ */ jsx("div", { className: "swt-muted", children: "No live markets right now." }),
181
- markets.map((m) => /* @__PURE__ */ jsxs(
317
+ /* @__PURE__ */ jsxs("div", { className: "swt-field", children: [
318
+ /* @__PURE__ */ jsxs("div", { className: "swt-label", children: [
319
+ /* @__PURE__ */ jsx("span", { className: "swt-step", children: "1" }),
320
+ " Pick a side"
321
+ ] }),
322
+ /* @__PURE__ */ jsx("div", { className: "swt-seg", role: "group", "aria-label": "Direction", children: ["long", "short"].map((s) => /* @__PURE__ */ jsxs(
182
323
  "button",
183
324
  {
184
325
  type: "button",
185
- onClick: () => setPicked(m.seriesId),
186
- className: `swt-tile${picked === m.seriesId ? " is-on" : ""}`,
326
+ onClick: () => setSide(s),
327
+ "aria-pressed": side === s,
328
+ className: `swt-seg-btn${side === s ? ` is-on is-${s}` : ""}`,
187
329
  children: [
188
- /* @__PURE__ */ jsx("div", { className: "swt-lev", children: m.leverage > 0 ? `${m.leverage.toFixed(0)}x` : "\u2014" }),
189
- /* @__PURE__ */ jsxs("div", { className: "swt-muted", children: [
190
- "ETH ",
191
- side === "long" ? ">" : "<",
192
- " $",
193
- (side === "long" ? m.strike + m.premium : m.strike - m.premium).toLocaleString(void 0, { maximumFractionDigits: 0 })
194
- ] }),
195
- /* @__PURE__ */ jsx("div", { className: "swt-muted-sm", children: "by expiry" })
330
+ /* @__PURE__ */ jsx("span", { className: "swt-seg-arrow", "aria-hidden": "true", children: s === "long" ? "\u2191" : "\u2193" }),
331
+ /* @__PURE__ */ jsxs("span", { className: "swt-seg-text", children: [
332
+ /* @__PURE__ */ jsx("span", { className: "swt-seg-title", children: s === "long" ? "Long" : "Short" }),
333
+ /* @__PURE__ */ jsxs("span", { className: "swt-seg-sub", children: [
334
+ "ETH ",
335
+ s === "long" ? "up" : "down"
336
+ ] })
337
+ ] })
196
338
  ]
197
339
  },
198
- m.seriesId
199
- ))
340
+ s
341
+ )) })
200
342
  ] }),
201
- /* @__PURE__ */ jsxs("div", { className: "swt-row", children: [
202
- /* @__PURE__ */ jsx("span", { className: "swt-muted", children: "$" }),
203
- /* @__PURE__ */ jsx(
204
- "input",
205
- {
206
- value: amount,
207
- onChange: (e) => setAmount(e.target.value),
208
- inputMode: "decimal",
209
- placeholder: "5",
210
- className: "swt-input"
211
- }
212
- ),
213
- /* @__PURE__ */ jsx("span", { className: "swt-muted", children: "USDC" }),
214
- /* @__PURE__ */ jsx(
215
- "button",
216
- {
217
- type: "button",
218
- onClick: onBuy,
219
- disabled: busy || picked === null,
220
- className: "swt-buy",
221
- children: busy ? "\u2026" : "Buy"
222
- }
223
- )
343
+ /* @__PURE__ */ jsxs("div", { className: "swt-field", children: [
344
+ /* @__PURE__ */ jsxs("div", { className: "swt-label", children: [
345
+ /* @__PURE__ */ jsx("span", { className: "swt-step", children: "2" }),
346
+ " Pick leverage"
347
+ ] }),
348
+ /* @__PURE__ */ jsxs("div", { className: "swt-tiles", children: [
349
+ loadingMarkets && [0, 1, 2].map((i) => /* @__PURE__ */ jsx("div", { className: "swt-tile swt-skel", "aria-hidden": "true" }, i)),
350
+ !loadingMarkets && markets.length === 0 && /* @__PURE__ */ jsx("div", { className: "swt-empty", children: "No live markets right now." }),
351
+ !loadingMarkets && markets.map((m) => {
352
+ const on = picked === m.seriesId;
353
+ return /* @__PURE__ */ jsxs(
354
+ "button",
355
+ {
356
+ type: "button",
357
+ onClick: () => setPicked(m.seriesId),
358
+ "aria-pressed": on,
359
+ className: `swt-tile${on ? " is-on" : ""}`,
360
+ children: [
361
+ /* @__PURE__ */ jsx("div", { className: "swt-lev", children: m.leverage > 0 ? `${m.leverage.toFixed(0)}x` : "\u2014" }),
362
+ /* @__PURE__ */ jsxs("div", { className: "swt-tile-be", children: [
363
+ "ETH ",
364
+ side === "long" ? ">" : "<",
365
+ " $",
366
+ fmtUsd(breakevenFor(m))
367
+ ] }),
368
+ /* @__PURE__ */ jsx("div", { className: "swt-tile-sub", children: "by expiry" })
369
+ ]
370
+ },
371
+ m.seriesId
372
+ );
373
+ })
374
+ ] })
375
+ ] }),
376
+ /* @__PURE__ */ jsxs("div", { className: "swt-field", children: [
377
+ /* @__PURE__ */ jsxs("div", { className: "swt-label", children: [
378
+ /* @__PURE__ */ jsx("span", { className: "swt-step", children: "3" }),
379
+ " Amount"
380
+ ] }),
381
+ /* @__PURE__ */ jsxs("div", { className: "swt-amount", children: [
382
+ /* @__PURE__ */ jsx("span", { className: "swt-cur", children: "$" }),
383
+ /* @__PURE__ */ jsx(
384
+ "input",
385
+ {
386
+ value: amount,
387
+ onChange: (e) => setAmount(e.target.value),
388
+ inputMode: "decimal",
389
+ placeholder: "5",
390
+ "aria-label": "Amount in USDC",
391
+ className: "swt-input"
392
+ }
393
+ ),
394
+ /* @__PURE__ */ jsx("span", { className: "swt-unit", children: "USDC" })
395
+ ] })
224
396
  ] }),
225
- hasPosition && /* @__PURE__ */ jsxs("div", { className: "swt-pos", children: [
226
- /* @__PURE__ */ jsxs("div", { children: [
227
- /* @__PURE__ */ jsx("div", { className: "swt-muted", children: "Your position" }),
228
- /* @__PURE__ */ jsxs("div", { children: [
229
- /* @__PURE__ */ jsx("strong", { children: position.qN.toFixed(4) }),
230
- " contracts \xB7 mark $",
231
- position.markUsd.toFixed(2)
397
+ /* @__PURE__ */ jsx(
398
+ "button",
399
+ {
400
+ type: "button",
401
+ onClick: onBuy,
402
+ disabled: !canBuy,
403
+ className: "swt-buy",
404
+ children: busy ? /* @__PURE__ */ jsx("span", { className: "swt-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
405
+ "Buy",
406
+ pickedMarket ? ` ${side === "long" ? "Long" : "Short"}` : "",
407
+ gasless && /* @__PURE__ */ jsx("span", { className: "swt-buy-sub", children: "gasless \xB7 one signature, no gas" })
408
+ ] })
409
+ }
410
+ ),
411
+ hasPosition && !gasless && /* @__PURE__ */ jsxs("div", { className: "swt-pos", children: [
412
+ /* @__PURE__ */ jsxs("div", { className: "swt-pos-head", children: [
413
+ /* @__PURE__ */ jsx("span", { className: "swt-pos-label", children: "Your position" }),
414
+ /* @__PURE__ */ jsxs("span", { className: `swt-side-pill is-${side}`, children: [
415
+ side === "long" ? "Long" : "Short",
416
+ pickedMarket && pickedMarket.leverage > 0 ? ` \xB7 ${pickedMarket.leverage.toFixed(0)}x` : ""
417
+ ] })
418
+ ] }),
419
+ /* @__PURE__ */ jsxs("div", { className: "swt-pos-grid", children: [
420
+ /* @__PURE__ */ jsxs("div", { className: "swt-stat", children: [
421
+ /* @__PURE__ */ jsx("span", { className: "swt-stat-k", children: "Size" }),
422
+ /* @__PURE__ */ jsx("span", { className: "swt-stat-v", children: position.qN.toFixed(4) }),
423
+ /* @__PURE__ */ jsx("span", { className: "swt-stat-u", children: "contracts" })
232
424
  ] }),
233
- /* @__PURE__ */ jsxs("div", { className: "swt-muted-sm", children: [
234
- "intrinsic $",
425
+ /* @__PURE__ */ jsxs("div", { className: "swt-stat", children: [
426
+ /* @__PURE__ */ jsx("span", { className: "swt-stat-k", children: "Value now" }),
427
+ /* @__PURE__ */ jsxs("span", { className: "swt-stat-v", children: [
428
+ "$",
429
+ position.markUsd.toFixed(2)
430
+ ] }),
431
+ paidUsd !== null && /* @__PURE__ */ jsxs("span", { className: "swt-stat-u", children: [
432
+ "paid $",
433
+ fmtUsd(paidUsd, 2)
434
+ ] })
435
+ ] })
436
+ ] }),
437
+ pnl !== null && /* @__PURE__ */ jsxs("div", { className: `swt-pnl${pnlUp ? " is-up" : " is-down"}`, children: [
438
+ /* @__PURE__ */ jsx("span", { className: "swt-pnl-k", children: "P&L" }),
439
+ /* @__PURE__ */ jsxs("span", { className: "swt-pnl-v", children: [
440
+ pnlUp ? "+" : "\u2212",
441
+ "$",
442
+ Math.abs(pnl).toFixed(2),
443
+ pnlPct !== null && /* @__PURE__ */ jsxs("span", { className: "swt-pnl-pct", children: [
444
+ " (",
445
+ pnlUp ? "+" : "\u2212",
446
+ Math.abs(pnlPct).toFixed(1),
447
+ "%)"
448
+ ] })
449
+ ] })
450
+ ] }),
451
+ /* @__PURE__ */ jsxs("div", { className: "swt-pos-foot", children: [
452
+ /* @__PURE__ */ jsxs("span", { className: "swt-intrinsic", children: [
453
+ "Settlement floor $",
235
454
  position.intrinsicUsd.toFixed(2)
455
+ ] }),
456
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, disabled: busy, className: "swt-close", children: busy ? /* @__PURE__ */ jsx("span", { className: "swt-spin swt-spin-dark", "aria-hidden": "true" }) : "Sell / Close" })
457
+ ] })
458
+ ] }),
459
+ canOfferLoad && /* @__PURE__ */ jsx(
460
+ "button",
461
+ {
462
+ type: "button",
463
+ onClick: onLoadPositions,
464
+ disabled: loadingPositions,
465
+ className: "swt-load",
466
+ children: loadingPositions ? /* @__PURE__ */ jsx("span", { className: "swt-spin swt-spin-dark", "aria-hidden": "true" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
467
+ /* @__PURE__ */ jsx("span", { className: "swt-load-title", children: "Load your Split positions" }),
468
+ /* @__PURE__ */ jsx("span", { className: "swt-load-sub", children: "one signature \xB7 reads positions opened earlier or on split.markets" })
236
469
  ] })
470
+ }
471
+ ),
472
+ showPositionsList && /* @__PURE__ */ jsxs("div", { className: "swt-open", children: [
473
+ /* @__PURE__ */ jsxs("div", { className: "swt-open-head", children: [
474
+ /* @__PURE__ */ jsx("span", { className: "swt-pos-label", children: "Open positions" }),
475
+ (positionsLoaded || trading) && !loadingPositions && /* @__PURE__ */ jsx(
476
+ "button",
477
+ {
478
+ type: "button",
479
+ onClick: () => loadPositions(),
480
+ disabled: loadingPositions,
481
+ className: "swt-refresh",
482
+ "aria-label": "Refresh positions",
483
+ children: "Refresh"
484
+ }
485
+ )
486
+ ] }),
487
+ loadingPositions && /* @__PURE__ */ jsxs("div", { className: "swt-open-state", children: [
488
+ /* @__PURE__ */ jsx("span", { className: "swt-spin swt-spin-dark", "aria-hidden": "true" }),
489
+ /* @__PURE__ */ jsx("span", { children: "Loading positions\u2026" })
237
490
  ] }),
238
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, disabled: busy, className: "swt-close", children: busy ? "\u2026" : "Close" })
491
+ !loadingPositions && positionsError && /* @__PURE__ */ jsx("div", { className: "swt-open-state is-err", children: positionsError }),
492
+ !loadingPositions && !positionsError && openPositions.length === 0 && /* @__PURE__ */ jsx("div", { className: "swt-open-state", children: "No open positions." }),
493
+ !loadingPositions && !positionsError && openPositions.map((p) => {
494
+ const key = posKey(p.side, p.seriesId);
495
+ const cost = costBasis[key];
496
+ const rowPnl = cost !== void 0 ? p.markUsd - cost : null;
497
+ const rowPnlUp = rowPnl !== null && rowPnl >= 0;
498
+ const selling = sellingKey === key;
499
+ return /* @__PURE__ */ jsxs("div", { className: "swt-row", children: [
500
+ /* @__PURE__ */ jsxs("div", { className: "swt-row-main", children: [
501
+ /* @__PURE__ */ jsxs("span", { className: `swt-side-pill is-${p.side}`, children: [
502
+ p.side === "long" ? "Long" : "Short",
503
+ p.leverage > 0 ? ` \xB7 ${p.leverage.toFixed(0)}x` : ""
504
+ ] }),
505
+ /* @__PURE__ */ jsxs("span", { className: "swt-row-size", children: [
506
+ p.qN.toFixed(4),
507
+ " contracts"
508
+ ] })
509
+ ] }),
510
+ /* @__PURE__ */ jsxs("div", { className: "swt-row-val", children: [
511
+ /* @__PURE__ */ jsxs("div", { className: "swt-row-now", children: [
512
+ /* @__PURE__ */ jsxs("span", { className: "swt-row-now-v", children: [
513
+ "$",
514
+ p.markUsd.toFixed(2)
515
+ ] }),
516
+ rowPnl !== null ? /* @__PURE__ */ jsxs("span", { className: `swt-row-pnl${rowPnlUp ? " is-up" : " is-down"}`, children: [
517
+ rowPnlUp ? "+" : "\u2212",
518
+ "$",
519
+ Math.abs(rowPnl).toFixed(2)
520
+ ] }) : /* @__PURE__ */ jsxs("span", { className: "swt-row-floor", children: [
521
+ "floor $",
522
+ p.intrinsicUsd.toFixed(2)
523
+ ] })
524
+ ] }),
525
+ /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ onClick: () => onSell(p),
530
+ disabled: selling || !!sellingKey,
531
+ className: "swt-close swt-row-sell",
532
+ children: selling ? /* @__PURE__ */ jsx("span", { className: "swt-spin swt-spin-dark", "aria-hidden": "true" }) : "Sell"
533
+ }
534
+ )
535
+ ] })
536
+ ] }, key);
537
+ })
239
538
  ] }),
240
- status && /* @__PURE__ */ jsx("div", { className: "swt-status", children: status })
539
+ status && /* @__PURE__ */ jsx("div", { className: `swt-status is-${statusKind}`, role: "status", children: status })
241
540
  ] })
242
541
  ] });
243
542
  }
@@ -252,24 +551,135 @@ function errMsg(e) {
252
551
  function css(root) {
253
552
  const r = `.${root}`;
254
553
  return `
255
- ${r} .swt-card{max-width:380px;border:1px solid color-mix(in srgb, var(--swt-text) 12%, transparent);border-radius:var(--swt-radius);padding:16px;background:var(--swt-bg);color:var(--swt-text);font-family:var(--swt-font);display:flex;flex-direction:column;gap:12px}
256
- ${r} .swt-head{display:flex;flex-direction:column;gap:4px}
257
- ${r} .swt-tag{font-size:12px;color:var(--swt-accent)}
258
- ${r} .swt-row{display:flex;gap:8px;align-items:center}
259
- ${r} .swt-toggle{flex:1;padding:8px 10px;border-radius:calc(var(--swt-radius) * 0.6);border:1px solid color-mix(in srgb, var(--swt-text) 16%, transparent);background:transparent;color:var(--swt-muted);cursor:pointer;font-family:inherit}
260
- ${r} .swt-toggle.is-on{background:color-mix(in srgb, var(--swt-accent) 18%, transparent);color:var(--swt-accent);border-color:color-mix(in srgb, var(--swt-accent) 50%, transparent)}
261
- ${r} .swt-tiles{display:grid;grid-template-columns:repeat(auto-fill, minmax(96px, 1fr));gap:8px}
262
- ${r} .swt-tile{padding:10px 8px;border-radius:calc(var(--swt-radius) * 0.6);border:1px solid color-mix(in srgb, var(--swt-text) 16%, transparent);background:transparent;color:var(--swt-text);cursor:pointer;text-align:center;font-family:inherit}
263
- ${r} .swt-tile.is-on{border-color:var(--swt-accent);background:color-mix(in srgb, var(--swt-accent) 14%, transparent)}
264
- ${r} .swt-lev{font-size:18px;font-weight:700}
265
- ${r} .swt-muted{color:var(--swt-muted);font-size:13px}
266
- ${r} .swt-muted-sm{color:color-mix(in srgb, var(--swt-muted) 80%, transparent);font-size:11px}
267
- ${r} .swt-input{flex:1;min-width:0;padding:8px 10px;border-radius:calc(var(--swt-radius) * 0.6);border:1px solid color-mix(in srgb, var(--swt-text) 16%, transparent);background:var(--swt-surface);color:var(--swt-text);font-family:inherit}
268
- ${r} .swt-buy{padding:8px 18px;border-radius:calc(var(--swt-radius) * 0.6);border:none;background:var(--swt-accent);color:#fff;font-weight:600;cursor:pointer;font-family:inherit}
269
- ${r} .swt-buy:disabled,${r} .swt-close:disabled{opacity:.6;cursor:default}
270
- ${r} .swt-pos{display:flex;justify-content:space-between;align-items:center;padding:12px;border-radius:calc(var(--swt-radius) * 0.75);background:var(--swt-surface)}
271
- ${r} .swt-close{padding:8px 14px;border-radius:calc(var(--swt-radius) * 0.6);border:1px solid color-mix(in srgb, var(--swt-text) 16%, transparent);background:transparent;color:var(--swt-text);cursor:pointer;font-family:inherit}
272
- ${r} .swt-status{font-size:12px;color:var(--swt-muted)}
554
+ ${r}{--_line:color-mix(in srgb, var(--swt-text) 10%, transparent);--_line-2:color-mix(in srgb, var(--swt-text) 18%, transparent);--_up:#16b67a;--_dn:#f0506a;--_rad:var(--swt-radius);--_rad-md:calc(var(--swt-radius) * 0.7);--_rad-sm:calc(var(--swt-radius) * 0.45);--_accent-soft:color-mix(in srgb, var(--swt-accent) 14%, transparent);box-sizing:border-box}
555
+ ${r} *,${r} *::before,${r} *::after{box-sizing:border-box}
556
+
557
+ ${r} .swt-card{width:100%;max-width:400px;border:1px solid var(--_line);border-radius:var(--_rad);padding:20px;background:
558
+ radial-gradient(120% 80% at 50% -10%, color-mix(in srgb, var(--swt-accent) 9%, transparent), transparent 60%),
559
+ var(--swt-bg);
560
+ color:var(--swt-text);font-family:var(--swt-font);display:flex;flex-direction:column;gap:16px;
561
+ box-shadow:0 1px 0 color-mix(in srgb, var(--swt-text) 6%, transparent) inset, 0 18px 40px -24px rgba(0,0,0,.55);-webkit-font-smoothing:antialiased}
562
+
563
+ ${r} .swt-head{display:flex;flex-direction:column;gap:8px}
564
+ ${r} .swt-brand{display:flex;align-items:center;gap:8px;font-size:16px;letter-spacing:-.01em}
565
+ ${r} .swt-logo{display:inline-flex;width:24px;height:24px;align-items:center;justify-content:center;border-radius:7px;font-size:13px;color:var(--swt-accent);background:var(--_accent-soft)}
566
+ ${r} .swt-tag{display:inline-flex;align-items:center;gap:7px;align-self:flex-start;font-size:11.5px;font-weight:600;letter-spacing:.01em;color:var(--swt-accent);background:var(--_accent-soft);border:1px solid color-mix(in srgb, var(--swt-accent) 28%, transparent);padding:4px 10px;border-radius:999px}
567
+ ${r} .swt-dot{width:6px;height:6px;border-radius:999px;background:var(--_up);box-shadow:0 0 0 3px color-mix(in srgb, var(--_up) 25%, transparent)}
568
+
569
+ ${r} .swt-field{display:flex;flex-direction:column;gap:8px}
570
+ ${r} .swt-label{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;color:var(--swt-muted);text-transform:uppercase;letter-spacing:.06em}
571
+ ${r} .swt-step{display:inline-flex;width:18px;height:18px;align-items:center;justify-content:center;border-radius:999px;font-size:11px;font-weight:700;color:var(--swt-accent);background:var(--_accent-soft)}
572
+
573
+ ${r} .swt-seg{display:grid;grid-template-columns:1fr 1fr;gap:8px}
574
+ ${r} .swt-seg-btn{display:flex;align-items:center;gap:10px;padding:12px 12px;border-radius:var(--_rad-md);border:1px solid var(--_line-2);background:var(--swt-surface);color:var(--swt-muted);cursor:pointer;font-family:inherit;text-align:left;transition:border-color .15s,background .15s,color .15s,transform .05s}
575
+ ${r} .swt-seg-btn:hover{border-color:color-mix(in srgb, var(--swt-text) 30%, transparent)}
576
+ ${r} .swt-seg-btn:active{transform:translateY(1px)}
577
+ ${r} .swt-seg-arrow{display:inline-flex;width:28px;height:28px;flex:0 0 auto;align-items:center;justify-content:center;border-radius:8px;font-size:15px;font-weight:800;background:color-mix(in srgb, var(--swt-text) 8%, transparent)}
578
+ ${r} .swt-seg-text{display:flex;flex-direction:column;line-height:1.15}
579
+ ${r} .swt-seg-title{font-size:14px;font-weight:700;color:var(--swt-text)}
580
+ ${r} .swt-seg-sub{font-size:11.5px;color:var(--swt-muted)}
581
+ ${r} .swt-seg-btn.is-on.is-long{border-color:color-mix(in srgb, var(--_up) 60%, transparent);background:color-mix(in srgb, var(--_up) 12%, var(--swt-surface));color:var(--swt-text)}
582
+ ${r} .swt-seg-btn.is-on.is-long .swt-seg-arrow{background:color-mix(in srgb, var(--_up) 22%, transparent);color:var(--_up)}
583
+ ${r} .swt-seg-btn.is-on.is-short{border-color:color-mix(in srgb, var(--_dn) 60%, transparent);background:color-mix(in srgb, var(--_dn) 12%, var(--swt-surface));color:var(--swt-text)}
584
+ ${r} .swt-seg-btn.is-on.is-short .swt-seg-arrow{background:color-mix(in srgb, var(--_dn) 22%, transparent);color:var(--_dn)}
585
+
586
+ ${r} .swt-tiles{display:grid;grid-template-columns:repeat(3, minmax(0, 1fr));gap:8px}
587
+ ${r} .swt-tile{display:flex;flex-direction:column;gap:3px;padding:12px 8px 10px;border-radius:var(--_rad-md);border:1px solid var(--_line-2);background:var(--swt-surface);color:var(--swt-text);cursor:pointer;text-align:center;font-family:inherit;transition:border-color .15s,background .15s,transform .05s}
588
+ ${r} .swt-tile:hover{border-color:color-mix(in srgb, var(--swt-text) 30%, transparent)}
589
+ ${r} .swt-tile:active{transform:translateY(1px)}
590
+ ${r} .swt-tile.is-on{border-color:var(--swt-accent);background:color-mix(in srgb, var(--swt-accent) 12%, var(--swt-surface));box-shadow:0 0 0 1px var(--swt-accent) inset}
591
+ ${r} .swt-lev{font-size:20px;font-weight:800;letter-spacing:-.02em;line-height:1}
592
+ ${r} .swt-tile.is-on .swt-lev{color:var(--swt-accent)}
593
+ ${r} .swt-tile-be{font-size:11px;font-weight:600;color:var(--swt-text);opacity:.85;white-space:nowrap}
594
+ ${r} .swt-tile-sub{font-size:10px;color:var(--swt-muted)}
595
+ ${r} .swt-skel{min-height:74px;cursor:default;background:linear-gradient(100deg, var(--swt-surface) 30%, color-mix(in srgb, var(--swt-text) 8%, var(--swt-surface)) 50%, var(--swt-surface) 70%);background-size:200% 100%;animation:swt-shimmer 1.2s linear infinite;border-color:var(--_line)}
596
+ ${r} .swt-skel:hover{border-color:var(--_line)}
597
+ ${r} .swt-empty{grid-column:1/-1;padding:14px;text-align:center;font-size:13px;color:var(--swt-muted);border:1px dashed var(--_line-2);border-radius:var(--_rad-md)}
598
+ @keyframes swt-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
599
+
600
+ ${r} .swt-amount{display:flex;align-items:center;gap:6px;padding:0 14px;border-radius:var(--_rad-md);border:1px solid var(--_line-2);background:var(--swt-surface);transition:border-color .15s,box-shadow .15s}
601
+ ${r} .swt-amount:focus-within{border-color:var(--swt-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--swt-accent) 22%, transparent)}
602
+ ${r} .swt-cur{font-size:16px;font-weight:700;color:var(--swt-muted)}
603
+ ${r} .swt-input{flex:1;min-width:0;padding:13px 2px;border:none;background:transparent;color:var(--swt-text);font-family:inherit;font-size:17px;font-weight:700;outline:none}
604
+ ${r} .swt-input::placeholder{color:var(--swt-muted);font-weight:600}
605
+ ${r} .swt-unit{font-size:12px;font-weight:600;color:var(--swt-muted)}
606
+
607
+ ${r} .swt-buy{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-height:52px;padding:11px 18px;border-radius:var(--_rad-md);border:none;
608
+ background:linear-gradient(180deg, color-mix(in srgb, var(--swt-accent) 92%, white), var(--swt-accent));
609
+ color:#fff;font-weight:700;font-size:15px;cursor:pointer;font-family:inherit;letter-spacing:.01em;
610
+ box-shadow:0 8px 20px -8px color-mix(in srgb, var(--swt-accent) 70%, transparent);transition:filter .15s,transform .05s,box-shadow .15s}
611
+ ${r} .swt-buy:hover:not(:disabled){filter:brightness(1.06)}
612
+ ${r} .swt-buy:active:not(:disabled){transform:translateY(1px);box-shadow:0 4px 12px -8px color-mix(in srgb, var(--swt-accent) 70%, transparent)}
613
+ ${r} .swt-buy:disabled{opacity:.5;cursor:not-allowed;box-shadow:none}
614
+ ${r} .swt-buy-sub{font-size:11px;font-weight:600;opacity:.85}
615
+
616
+ ${r} .swt-pos{display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:var(--_rad-md);border:1px solid var(--_line-2);background:
617
+ linear-gradient(180deg, color-mix(in srgb, var(--swt-accent) 6%, var(--swt-surface)), var(--swt-surface))}
618
+ ${r} .swt-pos-head{display:flex;align-items:center;justify-content:space-between}
619
+ ${r} .swt-pos-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--swt-muted)}
620
+ ${r} .swt-side-pill{font-size:11px;font-weight:700;padding:3px 9px;border-radius:999px;border:1px solid transparent}
621
+ ${r} .swt-side-pill.is-long{color:var(--_up);background:color-mix(in srgb, var(--_up) 14%, transparent);border-color:color-mix(in srgb, var(--_up) 35%, transparent)}
622
+ ${r} .swt-side-pill.is-short{color:var(--_dn);background:color-mix(in srgb, var(--_dn) 14%, transparent);border-color:color-mix(in srgb, var(--_dn) 35%, transparent)}
623
+ ${r} .swt-pos-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
624
+ ${r} .swt-stat{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border-radius:var(--_rad-sm);background:color-mix(in srgb, var(--swt-text) 4%, transparent)}
625
+ ${r} .swt-stat-k{font-size:11px;font-weight:600;color:var(--swt-muted)}
626
+ ${r} .swt-stat-v{font-size:18px;font-weight:800;letter-spacing:-.02em}
627
+ ${r} .swt-stat-u{font-size:11px;color:var(--swt-muted)}
628
+ ${r} .swt-pnl{display:flex;align-items:baseline;justify-content:space-between;padding:10px 12px;border-radius:var(--_rad-sm)}
629
+ ${r} .swt-pnl.is-up{background:color-mix(in srgb, var(--_up) 12%, transparent)}
630
+ ${r} .swt-pnl.is-down{background:color-mix(in srgb, var(--_dn) 12%, transparent)}
631
+ ${r} .swt-pnl-k{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--swt-muted)}
632
+ ${r} .swt-pnl-v{font-size:17px;font-weight:800;letter-spacing:-.01em}
633
+ ${r} .swt-pnl.is-up .swt-pnl-v{color:var(--_up)}
634
+ ${r} .swt-pnl.is-down .swt-pnl-v{color:var(--_dn)}
635
+ ${r} .swt-pnl-pct{font-size:12px;font-weight:700}
636
+ ${r} .swt-pos-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;padding-top:2px}
637
+ ${r} .swt-intrinsic{font-size:11px;color:var(--swt-muted)}
638
+ ${r} .swt-close{min-height:38px;padding:9px 16px;border-radius:var(--_rad-sm);border:1px solid var(--_line-2);background:var(--swt-bg);color:var(--swt-text);cursor:pointer;font-family:inherit;font-weight:700;font-size:13px;transition:border-color .15s,background .15s,transform .05s}
639
+ ${r} .swt-close:hover:not(:disabled){border-color:color-mix(in srgb, var(--_dn) 55%, transparent);color:var(--_dn)}
640
+ ${r} .swt-close:active:not(:disabled){transform:translateY(1px)}
641
+ ${r} .swt-close:disabled{opacity:.5;cursor:not-allowed}
642
+
643
+ ${r} .swt-load{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-height:48px;padding:10px 16px;border-radius:var(--_rad-md);border:1px dashed var(--_line-2);background:color-mix(in srgb, var(--swt-accent) 5%, transparent);color:var(--swt-text);cursor:pointer;font-family:inherit;transition:border-color .15s,background .15s,transform .05s}
644
+ ${r} .swt-load:hover:not(:disabled){border-color:color-mix(in srgb, var(--swt-accent) 55%, transparent);background:var(--_accent-soft)}
645
+ ${r} .swt-load:active:not(:disabled){transform:translateY(1px)}
646
+ ${r} .swt-load:disabled{opacity:.6;cursor:not-allowed}
647
+ ${r} .swt-load-title{font-size:13.5px;font-weight:700;color:var(--swt-accent)}
648
+ ${r} .swt-load-sub{font-size:11px;font-weight:500;color:var(--swt-muted);text-align:center}
649
+
650
+ ${r} .swt-open{display:flex;flex-direction:column;gap:10px;padding:16px;border-radius:var(--_rad-md);border:1px solid var(--_line-2);background:
651
+ linear-gradient(180deg, color-mix(in srgb, var(--swt-accent) 6%, var(--swt-surface)), var(--swt-surface))}
652
+ ${r} .swt-open-head{display:flex;align-items:center;justify-content:space-between;min-height:20px}
653
+ ${r} .swt-refresh{border:none;background:transparent;color:var(--swt-accent);cursor:pointer;font-family:inherit;font-size:11.5px;font-weight:700;letter-spacing:.02em;padding:2px 4px;border-radius:6px;transition:opacity .15s}
654
+ ${r} .swt-refresh:hover:not(:disabled){opacity:.75}
655
+ ${r} .swt-refresh:disabled{opacity:.5;cursor:not-allowed}
656
+ ${r} .swt-open-state{display:flex;align-items:center;justify-content:center;gap:8px;padding:14px;font-size:12.5px;color:var(--swt-muted);text-align:center}
657
+ ${r} .swt-open-state.is-err{color:var(--_dn)}
658
+ ${r} .swt-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 12px;border-radius:var(--_rad-sm);background:color-mix(in srgb, var(--swt-text) 4%, transparent)}
659
+ ${r} .swt-row-main{display:flex;flex-direction:column;gap:5px;min-width:0}
660
+ ${r} .swt-row-size{font-size:11.5px;color:var(--swt-muted)}
661
+ ${r} .swt-row-val{display:flex;align-items:center;gap:12px;flex:0 0 auto}
662
+ ${r} .swt-row-now{display:flex;flex-direction:column;align-items:flex-end;gap:2px;line-height:1.1}
663
+ ${r} .swt-row-now-v{font-size:15px;font-weight:800;letter-spacing:-.01em}
664
+ ${r} .swt-row-pnl{font-size:11.5px;font-weight:700}
665
+ ${r} .swt-row-pnl.is-up{color:var(--_up)}
666
+ ${r} .swt-row-pnl.is-down{color:var(--_dn)}
667
+ ${r} .swt-row-floor{font-size:10.5px;color:var(--swt-muted)}
668
+ ${r} .swt-row-sell{min-height:34px;padding:7px 14px}
669
+
670
+ ${r} .swt-status{font-size:12.5px;line-height:1.45;padding:9px 12px;border-radius:var(--_rad-sm);border:1px solid var(--_line)}
671
+ ${r} .swt-status.is-info{color:var(--swt-muted);background:color-mix(in srgb, var(--swt-text) 4%, transparent)}
672
+ ${r} .swt-status.is-ok{color:var(--_up);background:color-mix(in srgb, var(--_up) 10%, transparent);border-color:color-mix(in srgb, var(--_up) 30%, transparent)}
673
+ ${r} .swt-status.is-err{color:var(--_dn);background:color-mix(in srgb, var(--_dn) 10%, transparent);border-color:color-mix(in srgb, var(--_dn) 30%, transparent)}
674
+
675
+ ${r} .swt-spin{display:inline-block;width:18px;height:18px;border-radius:999px;border:2px solid color-mix(in srgb, #fff 45%, transparent);border-top-color:#fff;animation:swt-rot .6s linear infinite}
676
+ ${r} .swt-spin-dark{border-color:color-mix(in srgb, var(--swt-text) 30%, transparent);border-top-color:var(--swt-text);width:15px;height:15px}
677
+ @keyframes swt-rot{to{transform:rotate(360deg)}}
678
+
679
+ @media (max-width:360px){
680
+ ${r} .swt-card{padding:16px}
681
+ ${r} .swt-pos-grid{grid-template-columns:1fr}
682
+ }
273
683
  `;
274
684
  }
275
685
  var example_default = SplitTradeWidget;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitmarkets/sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Oracle-free, non-liquidatable ETH options — viem client + optional React widget for Split (split.markets). Integrate leverage your users can't get liquidated out of.",
5
5
  "license": "MIT",
6
6
  "type": "module",