@orbs-network/spot-ui 2.0.1 → 2.1.1

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 (55) hide show
  1. package/README.md +305 -0
  2. package/dist/spot-ui.js +2366 -2774
  3. package/dist/spot-ui.umd.cjs +11 -11
  4. package/dist/src/index.d.ts +12 -12
  5. package/dist/src/index.d.ts.map +1 -1
  6. package/dist/src/lib/analytics.d.ts +11 -13
  7. package/dist/src/lib/analytics.d.ts.map +1 -1
  8. package/dist/src/lib/api-config.d.ts +11 -0
  9. package/dist/src/lib/api-config.d.ts.map +1 -0
  10. package/dist/src/lib/build-repermit-order-data.d.ts +9 -9
  11. package/dist/src/lib/build-repermit-order-data.d.ts.map +1 -1
  12. package/dist/src/lib/client.d.ts +74 -0
  13. package/dist/src/lib/client.d.ts.map +1 -0
  14. package/dist/src/lib/evm-constants.d.ts +3 -0
  15. package/dist/src/lib/evm-constants.d.ts.map +1 -0
  16. package/dist/src/lib/order-form/amounts.d.ts +13 -0
  17. package/dist/src/lib/order-form/amounts.d.ts.map +1 -0
  18. package/dist/src/lib/order-form/calculate-order-form.d.ts +3 -0
  19. package/dist/src/lib/order-form/calculate-order-form.d.ts.map +1 -0
  20. package/dist/src/lib/order-form/constants.d.ts +10 -0
  21. package/dist/src/lib/order-form/constants.d.ts.map +1 -0
  22. package/dist/src/lib/order-form/prices.d.ts +8 -0
  23. package/dist/src/lib/order-form/prices.d.ts.map +1 -0
  24. package/dist/src/lib/order-form/schedule.d.ts +27 -0
  25. package/dist/src/lib/order-form/schedule.d.ts.map +1 -0
  26. package/dist/src/lib/order-form/types.d.ts +209 -0
  27. package/dist/src/lib/order-form/types.d.ts.map +1 -0
  28. package/dist/src/lib/order-form/validation.d.ts +7 -0
  29. package/dist/src/lib/order-form/validation.d.ts.map +1 -0
  30. package/dist/src/lib/order-form/values.d.ts +3 -0
  31. package/dist/src/lib/order-form/values.d.ts.map +1 -0
  32. package/dist/src/lib/orders/index.d.ts +7 -7
  33. package/dist/src/lib/orders/index.d.ts.map +1 -1
  34. package/dist/src/lib/orders/legacy-twap-config.d.ts +22 -0
  35. package/dist/src/lib/orders/legacy-twap-config.d.ts.map +1 -0
  36. package/dist/src/lib/orders/v1-orders.d.ts.map +1 -1
  37. package/dist/src/lib/orders/v2-orders.d.ts +3 -2
  38. package/dist/src/lib/orders/v2-orders.d.ts.map +1 -1
  39. package/dist/src/lib/partners.d.ts +3 -0
  40. package/dist/src/lib/partners.d.ts.map +1 -0
  41. package/dist/src/lib/public-links.d.ts +6 -0
  42. package/dist/src/lib/public-links.d.ts.map +1 -0
  43. package/dist/src/lib/submit-order.d.ts +2 -2
  44. package/dist/src/lib/submit-order.d.ts.map +1 -1
  45. package/dist/src/lib/types.d.ts +16 -8
  46. package/dist/src/lib/types.d.ts.map +1 -1
  47. package/dist/src/lib/utils.d.ts +1 -564
  48. package/dist/src/lib/utils.d.ts.map +1 -1
  49. package/package.json +7 -10
  50. package/dist/src/lib/consts.d.ts +0 -99
  51. package/dist/src/lib/consts.d.ts.map +0 -1
  52. package/dist/src/lib/lib.d.ts +0 -80
  53. package/dist/src/lib/lib.d.ts.map +0 -1
  54. package/dist/src/lib/networks.d.ts +0 -571
  55. package/dist/src/lib/networks.d.ts.map +0 -1
package/README.md ADDED
@@ -0,0 +1,305 @@
1
+ # Spot SDK
2
+
3
+ `@orbs-network/spot-ui` is the framework-agnostic Spot SDK. Use it from Vue,
4
+ Angular, Svelte, React, vanilla JavaScript, or a server-side TypeScript
5
+ application. It has no React dependency.
6
+
7
+ For the complete framework-neutral TypeScript workflow, see the
8
+ [`spot-integration` skill](https://github.com/orbs-network/spot-ui/tree/master/skills/spot-integration).
9
+
10
+ ## Complete form calculation
11
+
12
+ Use `calculateOrderForm` as the primary calculation API. Pass the DEX-owned
13
+ form state and market data; the SDK returns one authoritative model for both
14
+ display and order execution.
15
+
16
+ ```ts
17
+ import {
18
+ calculateOrderForm,
19
+ Module,
20
+ } from "@orbs-network/spot-ui";
21
+
22
+ const form = calculateOrderForm({
23
+ module: Module.TWAP,
24
+ inputTokenDecimals: inputToken.decimals,
25
+ outputTokenDecimals: outputToken.decimals,
26
+
27
+ // Raw output-token amount quoted for the complete input amount.
28
+ quotedOutputAmountRaw,
29
+ inputTokenUsdPrice,
30
+ outputTokenUsdPrice,
31
+ minTradeSizeUsd,
32
+ priceProtectionPercent: 3,
33
+ displayFeePercent,
34
+ inputBalanceRaw,
35
+
36
+ userInput: {
37
+ inputAmountUi,
38
+ isMarketOrder: true,
39
+
40
+ // Optional user overrides. Omit them to use SDK defaults.
41
+ tradeCount,
42
+ tradeInterval,
43
+ orderDuration,
44
+ limitPriceUi,
45
+ limitPricePercent,
46
+ triggerPriceUi,
47
+ triggerPricePercent,
48
+ isPriceInverted,
49
+ },
50
+ });
51
+ ```
52
+
53
+ The result includes:
54
+
55
+ ```ts
56
+ form.inputAmount; // raw, UI, and USD input amounts
57
+ form.outputAmount; // raw, UI, and USD output amounts
58
+ form.isInverted; // current price-display direction
59
+ form.trades; // trade count and structured per-trade input/output amounts
60
+ form.schedule; // resolved fill delay, duration, milliseconds, and errors
61
+ form.triggerPrice; // canonical raw value, display values, defaults, and validation
62
+ form.limitPrice; // canonical raw value, display values, defaults, and validation
63
+ form.minOutputAmountTotal; // raw, UI, and USD minimum total output
64
+ form.tradePrice; // raw, UI, and USD execution price
65
+ form.fees; // raw, UI, USD, and percentage fee values
66
+ form.values; // raw execution values used to build the order
67
+ form.errors; // structured errors, ordered list, and primary error
68
+ form.isReady;
69
+ form.canSubmit;
70
+ ```
71
+
72
+ Display amounts use `{ raw, ui, usd }` objects and
73
+ trade-direction terminology. For `limitPrice` and `triggerPrice`, `amount`
74
+ is now named `raw` and remains the canonical protocol rate, while
75
+ `display.raw`, `display.ui`, and `display.usd` follow the current `isInverted`
76
+ display direction. `form.values` intentionally contains no `UI` or `Usd`
77
+ fields. Integration-facing calculation and client APIs use input/output names.
78
+ Existing source/destination names remain only on low-level protocol helpers and
79
+ protocol response models such as `Order`.
80
+
81
+ This calculation is synchronous and does not fetch configuration. Optional
82
+ fields can be passed while the user edits the form; the result always contains
83
+ the currently derivable values. Editable fields live under `userInput`, while
84
+ token, quote, balance, and configuration data stay at the top level.
85
+ `userInput.inputAmountUi` is the single input amount. The SDK derives its raw
86
+ and USD representations from the token decimals and USD price.
87
+ `quotedOutputAmountRaw` is the raw output-token amount quoted for that complete
88
+ input amount; the SDK derives the per-token market rate from the two values.
89
+ Omit a stale quote while a replacement quote is loading.
90
+
91
+ `calculateOrderForm` is time-independent. Recalculate only when its form or
92
+ market inputs change. `prepareOrder` stamps the current start and deadline from
93
+ the calculated duration immediately before signing; those exact timestamps are
94
+ returned on `preparedOrder.values`.
95
+
96
+ `calculateOrderForm` is the only public order-calculation entry point. Its
97
+ smaller calculators are internal implementation details, so every integration
98
+ uses the same defaults, validation, and derived-value rules.
99
+
100
+ `minTradeSizeUsd` is a positive USD threshold owned by the integrating DEX.
101
+ Use the minimum approved for that partner/product; the SDK deliberately does
102
+ not guess protocol policy. `priceProtectionPercent` uses percentage units, so
103
+ `3` means 3% (300 basis points), not 3 bps. `displayFeePercent` is also a
104
+ percentage, but it only calculates `form.fees` for display. It does not collect
105
+ or subtract a fee; collection must be configured by the partner/backend.
106
+
107
+ ## Client and order submission
108
+
109
+ `createClient` loads RePermit configuration and returns a new initialized
110
+ client. It does not retain a module-level cache; the hosting application owns
111
+ client reuse, request deduplication, and refresh policy. Initialization rejects
112
+ chain mismatches and malformed or zero RePermit and exchange-adapter addresses
113
+ before exposing approval or cancellation values.
114
+
115
+ ### Migrating from 1.x
116
+
117
+ Version 2 uses `calculateOrderForm` as the single calculation entry point and
118
+ an initialized `createClient` for order preparation, signing, submission,
119
+ cancellation requests, and configured history. Legacy low-level order-building
120
+ and submission exports were removed so integrations cannot bypass the shared
121
+ validated form and client configuration.
122
+
123
+ ```ts
124
+ import {
125
+ calculateOrderForm,
126
+ createClient,
127
+ isNativeAddress,
128
+ isTxRejected,
129
+ Module,
130
+ Partners,
131
+ } from "@orbs-network/spot-ui";
132
+
133
+ const client = await createClient(Partners.Quick, 137);
134
+
135
+ const form = calculateOrderForm({
136
+ module: Module.TWAP,
137
+ inputTokenDecimals: inputToken.decimals,
138
+ outputTokenDecimals: outputToken.decimals,
139
+ quotedOutputAmountRaw,
140
+ inputTokenUsdPrice,
141
+ outputTokenUsdPrice,
142
+ minTradeSizeUsd,
143
+ priceProtectionPercent: 3,
144
+ displayFeePercent,
145
+ inputBalanceRaw,
146
+ userInput: {
147
+ inputAmountUi,
148
+ isMarketOrder: true,
149
+ tradeCount,
150
+ tradeInterval,
151
+ orderDuration,
152
+ limitPriceUi,
153
+ limitPricePercent,
154
+ triggerPriceUi,
155
+ triggerPricePercent,
156
+ isPriceInverted,
157
+ },
158
+ });
159
+
160
+ const amount = form.inputAmount.raw;
161
+ const orderInputToken = isNativeAddress(inputToken.address)
162
+ ? wrappedNativeToken
163
+ : inputToken;
164
+ if (!orderInputToken) {
165
+ throw new Error("The host must provide the chain's wrapped native token");
166
+ }
167
+ const approvalRequest = {
168
+ tokenAddress: orderInputToken.address,
169
+ amount,
170
+ spenderAddress: client.spenderAddress,
171
+ };
172
+ const { tokenAddress, spenderAddress } = approvalRequest;
173
+ const hasAllowance = async () =>
174
+ BigInt(await wallet.getAllowance({ tokenAddress, spenderAddress })) >=
175
+ BigInt(amount);
176
+
177
+ try {
178
+ const approvalRequired = !(await hasAllowance());
179
+
180
+ // The signed order spends wrapped native tokens, so wrap before approval.
181
+ if (isNativeAddress(inputToken.address)) {
182
+ await wallet.wrapNativeToken(amount);
183
+ }
184
+
185
+ if (approvalRequired) {
186
+ await wallet.approveToken(approvalRequest);
187
+
188
+ // Allow RPC allowance state to catch up after the confirmed approval.
189
+ for (let attempt = 0; attempt < 3 && !(await hasAllowance()); attempt++) {
190
+ await new Promise((resolve) => setTimeout(resolve, 3_000));
191
+ }
192
+ if (!(await hasAllowance())) throw new Error("Approval was not observed");
193
+ }
194
+
195
+ const preparedOrder = client.prepareOrder({
196
+ form,
197
+ inputTokenAddress: orderInputToken.address,
198
+ outputTokenAddress: outputToken.address,
199
+ swapperAddress: account,
200
+ });
201
+ const signature = await client.signOrder(
202
+ preparedOrder,
203
+ ({ signerAddress, typedData }) =>
204
+ wallet.signTypedData(typedData, signerAddress),
205
+ );
206
+ const order = await client.submitOrder(preparedOrder, signature);
207
+ console.info("Order submitted", order);
208
+ } catch (error) {
209
+ if (isTxRejected(error)) console.info("The wallet request was rejected");
210
+ else throw error;
211
+ }
212
+ ```
213
+
214
+ `signOrder` only invokes the supplied wallet signer and returns its signature.
215
+ It never submits the order. `submitOrder` is the separate network operation.
216
+ The complete sequence is allowance check, native wrapping when required,
217
+ approval when required, allowance verification, signing, and submission.
218
+
219
+ `prepareOrder` does not recalculate form amounts, prices, trades, or schedules,
220
+ and it rejects a form whose `canSubmit` value is `false`.
221
+ It stamps the current start and deadline from the calculated duration, then
222
+ converts the supplied form into RePermit, signing, and approval data. The
223
+ returned `PreparedOrder` contains:
224
+
225
+ - `form`, the complete calculated form snapshot shown to the user;
226
+ - `values`, `form.values` plus the exact preparation-time timestamps used by the
227
+ signed order;
228
+ - `order`, the resulting protocol order;
229
+ - `signingRequest`, containing a framework-neutral `signerAddress` and
230
+ `typedData` EIP-712 payload;
231
+ - `approvalRequest`, ready for the wallet approval adapter.
232
+
233
+ Each `prepareOrder` call assigns a fresh monotonic nonce within that client
234
+ instance, so two orders prepared by the same instance cannot reuse a nonce. A
235
+ new client instance starts again from the current wall-clock value. The call
236
+ also assigns fresh `currentTimeMillis` and `deadlineMillis` values for that
237
+ submission attempt. Call it after wrapping and approval, immediately before
238
+ signing, so those time-dependent values remain fresh.
239
+
240
+ The signing request does not depend on Viem, Wagmi, Ethers, or another wallet
241
+ library. Viem adapters can spread `typedData` and map `signerAddress` to
242
+ `account`; Ethers adapters can pass `typedData.domain`, `typedData.types`, and
243
+ `typedData.message` to the signer.
244
+
245
+ `minTradeSizeUsd` is required calculation input owned by the integrating
246
+ application. The client does not read or infer it from partner configuration.
247
+
248
+ The complete form calculation remains a package-level function because it does
249
+ not depend on partner or chain configuration. The client exposes only
250
+ configured operations:
251
+
252
+ ```ts
253
+ calculateOrderForm(formParams);
254
+ client.getCancelOrderRequest(order);
255
+ client.getAccountOrders({ account });
256
+ ```
257
+
258
+ Omitting `page` fetches every available history page. To fetch one page, pass
259
+ a zero-based `page` and an optional positive `limit`. Use `order.historyKey`
260
+ as the stable list/cache identity: legacy v1 numeric IDs can repeat across TWAP
261
+ contract deployments, while `order.id` remains the protocol order ID used for
262
+ display and cancellation.
263
+
264
+ The normalized history model keeps protocol response names (`src`/`dst` and
265
+ fill `in`/`out`) because it combines v1 and v2 payloads. Form and calculation
266
+ inputs use `input`/`output`. `OrderType` maps the selected module and execution
267
+ mode into `LIMIT`, `TWAP_LIMIT`, `TWAP_MARKET`, `STOP_LOSS_LIMIT`,
268
+ `STOP_LOSS_MARKET`, `TAKE_PROFIT_LIMIT`, or `TAKE_PROFIT_MARKET`.
269
+ `OrderFilter` provides `ALL`, `OPEN`, `COMPLETED`, `CANCELLED`, and `EXPIRED`
270
+ history filter values.
271
+
272
+ There is no authoritative single-order endpoint in the current service API.
273
+ To track an order, call `client.getAccountOrders({ account, page, limit })` on
274
+ the host's polling schedule and find it by `historyKey`. Supplying a page and
275
+ limit avoids fetching every history page when only a recent status window is
276
+ needed.
277
+
278
+ Use `client.spenderAddress` for allowance reads and approvals. When the input
279
+ is native, the host must pass its chain's wrapped native token address to
280
+ `prepareOrder`; approve `form.inputAmount.raw` against that same token.
281
+ The `approvalRequest` returned by `prepareOrder` records the same normalized
282
+ token, spender, and exact amount used by the signed order.
283
+
284
+ `spot-ui` deliberately has no network registry and does not infer wrapped-token
285
+ or explorer metadata. The host DEX owns that chain data. Protocol configuration
286
+ fetching, RePermit order
287
+ construction, submission, cancellation request construction, and configured
288
+ history access are intentionally exposed only through `SpotClient`. This keeps
289
+ partner- and chain-derived values on one authoritative path.
290
+
291
+ Framework-neutral helpers such as `isNativeAddress` and `isTxRejected` remain
292
+ available to Vue, Angular, Svelte, vanilla JavaScript, and server integrations.
293
+
294
+ Every `createClient` call performs a new configuration request. Cache the
295
+ returned promise or client in the host application's normal data layer when it
296
+ should be reused. `spot-react` keeps one provider-scoped client resource keyed
297
+ by partner and chain; it does not require React Query. Vue, Angular, Svelte,
298
+ vanilla JavaScript, and server applications should apply their own lifecycle
299
+ and refresh policy.
300
+
301
+ ```ts
302
+ // Illustrative host-owned cache; use the host framework's data layer where possible.
303
+ const clientPromise = createClient(Partners.Quick, 137);
304
+ const client = await clientPromise;
305
+ ```