@silentswap/react 0.0.79 → 0.0.80

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.
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { NaiveBase58, RefundEligibility } from '@silentswap/sdk';
3
3
  import type { SilentSwapWallet } from '../hooks/silent/useWallet.js';
4
+ import { type OrderTrackingState, type OrderTrackingOptions } from './orderTrackingTypes.js';
4
5
  export type OrdersContextOrderMetadata = {
5
6
  sourceAsset?: {
6
7
  caip19: string;
@@ -53,6 +54,10 @@ export type OrdersContextType = {
53
54
  pulsing: boolean;
54
55
  color: string;
55
56
  };
57
+ orderTrackingByKey: Record<string, OrderTrackingState>;
58
+ connectOrderTracking: (orderId: string, auth: string, options: OrderTrackingOptions) => void;
59
+ disconnectOrderTracking: (orderId: string, auth: string) => void;
60
+ getOrderTrackingState: (orderId: string, auth: string) => OrderTrackingState;
56
61
  };
57
62
  export declare const OrdersProvider: React.FC<{
58
63
  children: React.ReactNode;
@@ -4,6 +4,8 @@ import { createContext, useContext, useState, useEffect, useCallback, useMemo, u
4
4
  import { bytes_to_base58, DepositStatus, hex_to_bytes } from '@silentswap/sdk';
5
5
  import { useLocalStorage } from 'usehooks-ts';
6
6
  import { useSilentSwap } from './SilentSwapContext.js';
7
+ import { createOrderTrackingManager } from './orderTrackingConnection.js';
8
+ import { getOrderTrackingCacheKey, DEFAULT_ORDER_TRACKING_STATE, } from './orderTrackingTypes.js';
7
9
  export const useWalletFacilitatorGroups = (wallet, setFacilitatorGroups) => {
8
10
  // Automatically set facilitator groups from wallet (matches Svelte behavior)
9
11
  // In Svelte: UserState.facilitatorGroups = a_accounts.map(g => g.group) when wallet loads
@@ -29,6 +31,48 @@ export const OrdersProvider = ({ children, baseUrl: baseUrlProp }) => {
29
31
  const [orderIdToViewingAuth, setOrderIdToViewingAuth] = useLocalStorage('orderIdToViewingAuth', {}, { initializeWithValue: true });
30
32
  const [orderIdToDefaultPublicKey, setOrderIdToDefaultPublicKey] = useLocalStorage('orderIdToDefaultPublicKey', {}, { initializeWithValue: true });
31
33
  const [orderIdToDestinations, setOrderIdToDestinationsState] = useLocalStorage('orderIdToDestinations', {}, { initializeWithValue: true });
34
+ // Order tracking: WebSocket connections and status cache live in context
35
+ const [orderTrackingByKey, setOrderTrackingByKey] = useState({});
36
+ const orderTrackingStateRef = useRef(new Map());
37
+ const activeTrackingKeysRef = useRef(new Set());
38
+ const optionsByKeyRef = useRef(new Map());
39
+ // Stable API object: only setStateForKey needs a ref so it always sees latest setOrderTrackingByKey
40
+ const setStateForKeyRef = useRef(null);
41
+ setStateForKeyRef.current = (key, state) => {
42
+ orderTrackingStateRef.current.set(key, state);
43
+ setOrderTrackingByKey((prev) => ({ ...prev, [key]: state }));
44
+ };
45
+ const orderTrackingApiRef = useRef({
46
+ setStateForKey(key, state) {
47
+ setStateForKeyRef.current(key, state);
48
+ },
49
+ getStateForKey(key) {
50
+ return orderTrackingStateRef.current.get(key);
51
+ },
52
+ isKeyActive(key) {
53
+ return activeTrackingKeysRef.current.has(key);
54
+ },
55
+ getOptionsForKey(key) {
56
+ return optionsByKeyRef.current.get(key);
57
+ },
58
+ });
59
+ const orderTrackingManager = useMemo(() => createOrderTrackingManager(orderTrackingApiRef), []);
60
+ const connectOrderTracking = useCallback((orderId, auth, options) => {
61
+ const key = getOrderTrackingCacheKey(orderId, auth);
62
+ activeTrackingKeysRef.current.add(key);
63
+ optionsByKeyRef.current.set(key, options);
64
+ orderTrackingManager.connect(orderId, auth, key, options);
65
+ }, [orderTrackingManager]);
66
+ const disconnectOrderTracking = useCallback((orderId, auth) => {
67
+ const key = getOrderTrackingCacheKey(orderId, auth);
68
+ activeTrackingKeysRef.current.delete(key);
69
+ optionsByKeyRef.current.delete(key);
70
+ orderTrackingManager.disconnect(orderId, auth);
71
+ }, [orderTrackingManager]);
72
+ const getOrderTrackingState = useCallback((orderId, auth) => {
73
+ const key = getOrderTrackingCacheKey(orderId, auth);
74
+ return orderTrackingByKey[key] ?? DEFAULT_ORDER_TRACKING_STATE;
75
+ }, [orderTrackingByKey]);
32
76
  // Generate viewing auth token from facilitator group
33
77
  const facilitator_group_authorize_order_view = useCallback(async (groupGetter) => {
34
78
  try {
@@ -254,6 +298,10 @@ export const OrdersProvider = ({ children, baseUrl: baseUrlProp }) => {
254
298
  refreshOrders,
255
299
  getOrderAgeText,
256
300
  getStatusInfo,
301
+ orderTrackingByKey,
302
+ connectOrderTracking,
303
+ disconnectOrderTracking,
304
+ getOrderTrackingState,
257
305
  }), [
258
306
  orders,
259
307
  loading,
@@ -269,6 +317,10 @@ export const OrdersProvider = ({ children, baseUrl: baseUrlProp }) => {
269
317
  refreshOrders,
270
318
  getOrderAgeText,
271
319
  getStatusInfo,
320
+ orderTrackingByKey,
321
+ connectOrderTracking,
322
+ disconnectOrderTracking,
323
+ getOrderTrackingState,
272
324
  ]);
273
325
  return _jsx(OrdersContext.Provider, { value: value, children: children });
274
326
  };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Order tracking WebSocket and cache logic.
3
+ * Lives in context via createOrderTrackingManager(); state updates go through setStateForKey.
4
+ */
5
+ import type { OrderTrackingState, OrderTrackingOptions } from './orderTrackingTypes.js';
6
+ export type OrderTrackingManagerApi = {
7
+ setStateForKey: (key: string, state: OrderTrackingState) => void;
8
+ getStateForKey: (key: string) => OrderTrackingState | undefined;
9
+ isKeyActive: (key: string) => boolean;
10
+ getOptionsForKey: (key: string) => OrderTrackingOptions | undefined;
11
+ };
12
+ /** Ref-like object so the manager always reads the current API (avoids storing manager in a ref). */
13
+ export type OrderTrackingManagerApiRef = {
14
+ current: OrderTrackingManagerApi;
15
+ };
16
+ export declare function createOrderTrackingManager(apiRef: OrderTrackingManagerApiRef): {
17
+ connect: (orderId: string, auth: string, key: string, options: OrderTrackingOptions) => void;
18
+ disconnect: (orderId: string, auth: string) => void;
19
+ };
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Order tracking WebSocket and cache logic.
3
+ * Lives in context via createOrderTrackingManager(); state updates go through setStateForKey.
4
+ */
5
+ import { OutputStage, DEFAULT_ORDER_TRACKING_STATE, getStatusTextFromStage, getProgressFromStage, hasFinalizedOutput, isFullOrderStatus, getOrderTrackingCacheKey, buildOrderTrackingWsUrl, } from './orderTrackingTypes.js';
6
+ const wsCache = new Map();
7
+ const pendingCleanups = new Map();
8
+ const statusCache = new Map();
9
+ function buildFullState(key, status, isConnected, isLoading, error) {
10
+ const outputsList = status.outputs ?? [];
11
+ const numOutputs = outputsList.length || 1;
12
+ const newOutputs = [];
13
+ const newProgresses = [];
14
+ const newStatusTexts = [];
15
+ for (let index = 0; index < outputsList.length; index++) {
16
+ const output = outputsList[index];
17
+ const outputAsset = output.output ??
18
+ (output.asset
19
+ ? { caip19: output.asset, amount: output.value || '0', decimals: 0 }
20
+ : undefined);
21
+ newOutputs.push({
22
+ index,
23
+ stage: output.stage,
24
+ timestamp: output.timestamp,
25
+ recipient: output.recipient,
26
+ asset: outputAsset,
27
+ txs: output.txs,
28
+ });
29
+ newProgresses.push(getProgressFromStage(output.stage));
30
+ newStatusTexts.push(getStatusTextFromStage(output.stage));
31
+ }
32
+ const allFinalized = newOutputs.length > 0 && newOutputs.every((o) => o.stage === OutputStage.FINALIZED);
33
+ const completedTimestamp = outputsList.length > 0
34
+ ? outputsList.reduce((min, o) => (min == null || o.timestamp < min ? o.timestamp : min), null)
35
+ : null;
36
+ return {
37
+ isConnected,
38
+ isLoading,
39
+ error,
40
+ orderStatus: status,
41
+ deposit: status.deposit
42
+ ? {
43
+ amount: status.deposit.amount,
44
+ timestamp: status.deposit.timestamp,
45
+ duration: status.deposit.duration,
46
+ orderId: status.deposit.orderId,
47
+ tx: status.deposit.tx,
48
+ }
49
+ : null,
50
+ outputs: newOutputs.length ? newOutputs : [],
51
+ progresses: newProgresses.length ? newProgresses : new Array(numOutputs).fill(undefined),
52
+ statusTexts: newStatusTexts.length ? newStatusTexts : new Array(numOutputs).fill('Connecting'),
53
+ completedTimestamp: allFinalized ? completedTimestamp : null,
54
+ isComplete: allFinalized,
55
+ };
56
+ }
57
+ function applyFullStatus(getApi, key, status, cacheConn, isConnected, isLoading, error) {
58
+ const api = getApi();
59
+ const current = api.getStateForKey(key)?.orderStatus;
60
+ const currentFinalized = current && hasFinalizedOutput(current);
61
+ const incomingFinalized = hasFinalizedOutput(status);
62
+ if (currentFinalized && !incomingFinalized)
63
+ return;
64
+ if (cacheConn) {
65
+ cacheConn.initialStatus = status;
66
+ statusCache.set(getOrderTrackingCacheKey(cacheConn.orderId, cacheConn.auth), status);
67
+ }
68
+ const state = buildFullState(key, status, isConnected, isLoading, error);
69
+ api.setStateForKey(key, state);
70
+ api.getOptionsForKey(key)?.onStatusUpdate?.(status);
71
+ }
72
+ function submitRequest(conn, method, params, handler) {
73
+ if (conn.ws.readyState !== WebSocket.OPEN)
74
+ return -1;
75
+ const requestId = conn.requestCounter++;
76
+ const request = { jsonrpc: '2.0', id: requestId, method, params };
77
+ if (handler)
78
+ conn.responseHandlers.set(requestId, handler);
79
+ conn.ws.send(JSON.stringify(request));
80
+ return requestId;
81
+ }
82
+ export function createOrderTrackingManager(apiRef) {
83
+ const getApi = () => apiRef.current;
84
+ const reconnectTimeoutRef = { current: null };
85
+ function handleStatusUpdate(key, update, conn, getCurrentState) {
86
+ conn.statusUpdates.push(update);
87
+ const prev = getCurrentState() ?? DEFAULT_ORDER_TRACKING_STATE;
88
+ let next = { ...prev };
89
+ switch (update.type) {
90
+ case 'deposit':
91
+ next = {
92
+ ...next,
93
+ deposit: {
94
+ amount: update.data.amount,
95
+ timestamp: update.data.timestamp,
96
+ duration: update.data.duration,
97
+ orderId: update.data.orderId,
98
+ tx: update.data.tx,
99
+ },
100
+ };
101
+ break;
102
+ case 'stage': {
103
+ const idx = update.data.index;
104
+ const progress = getProgressFromStage(update.data.stage);
105
+ const statusText = getStatusTextFromStage(update.data.stage);
106
+ const newOutputs = [...(next.outputs || [])];
107
+ newOutputs[idx] = {
108
+ ...newOutputs[idx],
109
+ index: idx,
110
+ stage: update.data.stage,
111
+ timestamp: update.data.timestamp,
112
+ ...(update.data.asset ? { asset: update.data.asset } : {}),
113
+ };
114
+ const newProgresses = [...(next.progresses || [])];
115
+ newProgresses[idx] = progress;
116
+ const newStatusTexts = [...(next.statusTexts || [])];
117
+ newStatusTexts[idx] = statusText;
118
+ next = {
119
+ ...next,
120
+ outputs: newOutputs,
121
+ progresses: newProgresses,
122
+ statusTexts: newStatusTexts,
123
+ };
124
+ const allOne = newProgresses.every((p) => (p ?? 0) >= 1);
125
+ if (allOne) {
126
+ next = {
127
+ ...next,
128
+ isComplete: true,
129
+ completedTimestamp: next.completedTimestamp ?? update.data.timestamp,
130
+ };
131
+ getApi().getOptionsForKey(key)?.onComplete?.();
132
+ }
133
+ break;
134
+ }
135
+ case 'transaction': {
136
+ const newOutputs = [...(next.outputs || [])];
137
+ if (newOutputs[update.data.index]) {
138
+ const existingTxs = newOutputs[update.data.index].txs || {};
139
+ newOutputs[update.data.index] = {
140
+ ...newOutputs[update.data.index],
141
+ txs: {
142
+ ...existingTxs,
143
+ [update.data.kind]: {
144
+ txId: update.data.txId,
145
+ chain: update.data.chain,
146
+ },
147
+ },
148
+ };
149
+ }
150
+ next = { ...next, outputs: newOutputs };
151
+ break;
152
+ }
153
+ case 'error': {
154
+ const err = new Error(update.data.message || 'Order tracking error');
155
+ next = { ...next, error: err };
156
+ getApi().getOptionsForKey(key)?.onError?.(err);
157
+ break;
158
+ }
159
+ }
160
+ getApi().setStateForKey(key, next);
161
+ }
162
+ function connect(orderId, auth, key, options) {
163
+ const client = options.client;
164
+ const pendingCleanup = pendingCleanups.get(key);
165
+ if (pendingCleanup) {
166
+ clearTimeout(pendingCleanup);
167
+ pendingCleanups.delete(key);
168
+ }
169
+ if (reconnectTimeoutRef.current) {
170
+ clearTimeout(reconnectTimeoutRef.current);
171
+ reconnectTimeoutRef.current = null;
172
+ }
173
+ const cached = wsCache.get(key);
174
+ if (cached &&
175
+ (cached.ws.readyState === WebSocket.OPEN || cached.ws.readyState === WebSocket.CONNECTING)) {
176
+ if (cached.initialStatus) {
177
+ const status = cached.initialStatus;
178
+ applyFullStatus(getApi, key, status, cached, true, false, null);
179
+ }
180
+ return;
181
+ }
182
+ wsCache.delete(key);
183
+ const cachedStatus = statusCache.get(key);
184
+ if (cachedStatus) {
185
+ applyFullStatus(getApi, key, cachedStatus, null, false, false, null);
186
+ }
187
+ else {
188
+ getApi().setStateForKey(key, {
189
+ ...DEFAULT_ORDER_TRACKING_STATE,
190
+ isLoading: true,
191
+ });
192
+ }
193
+ const wsUrl = buildOrderTrackingWsUrl(client);
194
+ let ws;
195
+ try {
196
+ ws = new WebSocket(wsUrl);
197
+ }
198
+ catch (err) {
199
+ const e = err instanceof Error ? err : new Error('Failed to connect to order tracking');
200
+ getApi().setStateForKey(key, {
201
+ ...DEFAULT_ORDER_TRACKING_STATE,
202
+ error: e,
203
+ isLoading: false,
204
+ });
205
+ options.onError?.(e);
206
+ return;
207
+ }
208
+ const conn = {
209
+ ws,
210
+ orderId,
211
+ auth,
212
+ requestCounter: 0,
213
+ responseHandlers: new Map(),
214
+ lastReceived: 0,
215
+ reconnectTimeout: null,
216
+ initialStatus: null,
217
+ statusUpdates: [],
218
+ };
219
+ wsCache.set(key, conn);
220
+ ws.onopen = () => {
221
+ conn.lastReceived = Date.now();
222
+ const connectRequestId = submitRequest(conn, 'connect', { auth: { orderId, viewingAuth: auth } }, (rpcError, result) => {
223
+ if (rpcError) {
224
+ const err = new Error(rpcError.message || 'Connection error');
225
+ if (!getApi().isKeyActive(key))
226
+ return;
227
+ getApi().setStateForKey(key, {
228
+ ...DEFAULT_ORDER_TRACKING_STATE,
229
+ error: err,
230
+ isLoading: false,
231
+ });
232
+ getApi().getOptionsForKey(key)?.onError?.(err);
233
+ return;
234
+ }
235
+ if (!getApi().isKeyActive(key))
236
+ return;
237
+ const status = result;
238
+ conn.statusUpdates = [];
239
+ applyFullStatus(getApi, key, status, conn, true, false, null);
240
+ if (connectRequestId >= 0) {
241
+ conn.responseHandlers.set(connectRequestId, (statusError, statusResult) => {
242
+ if (statusError) {
243
+ const err = new Error(statusError.message || 'Status error');
244
+ if (!getApi().isKeyActive(key))
245
+ return;
246
+ const prev = getApi().getStateForKey(key) ?? DEFAULT_ORDER_TRACKING_STATE;
247
+ getApi().setStateForKey(key, { ...prev, error: err });
248
+ getApi().getOptionsForKey(key)?.onError?.(err);
249
+ return;
250
+ }
251
+ if (!getApi().isKeyActive(key))
252
+ return;
253
+ if (isFullOrderStatus(statusResult)) {
254
+ applyFullStatus(getApi, key, statusResult, conn, true, false, null);
255
+ return;
256
+ }
257
+ handleStatusUpdate(key, statusResult, conn, () => getApi().getStateForKey(key));
258
+ });
259
+ }
260
+ getApi().getOptionsForKey(key)?.onStatusUpdate?.(status);
261
+ });
262
+ };
263
+ ws.onmessage = (event) => {
264
+ conn.lastReceived = Date.now();
265
+ try {
266
+ const response = JSON.parse(event.data);
267
+ if (response.jsonrpc !== '2.0' || typeof response.id !== 'number')
268
+ return;
269
+ const handler = conn.responseHandlers.get(response.id);
270
+ if (handler)
271
+ handler(response.error, response.result);
272
+ }
273
+ catch {
274
+ // ignore
275
+ }
276
+ };
277
+ ws.onerror = () => {
278
+ if (!getApi().isKeyActive(key))
279
+ return;
280
+ const prev = getApi().getStateForKey(key) ?? DEFAULT_ORDER_TRACKING_STATE;
281
+ getApi().setStateForKey(key, {
282
+ ...prev,
283
+ error: new Error('WebSocket connection error'),
284
+ isLoading: false,
285
+ });
286
+ };
287
+ ws.onclose = () => {
288
+ if (wsCache.get(key)?.ws === ws)
289
+ wsCache.delete(key);
290
+ conn.responseHandlers.clear();
291
+ conn.initialStatus = null;
292
+ conn.statusUpdates = [];
293
+ if (getApi().isKeyActive(key)) {
294
+ const prev = getApi().getStateForKey(key) ?? DEFAULT_ORDER_TRACKING_STATE;
295
+ getApi().setStateForKey(key, { ...prev, isConnected: false });
296
+ const idle = Date.now() - conn.lastReceived > 90_000;
297
+ if (idle) {
298
+ reconnectTimeoutRef.current = setTimeout(() => {
299
+ if (getApi().isKeyActive(key))
300
+ connect(orderId, auth, key, getApi().getOptionsForKey(key) ?? {});
301
+ }, 5000);
302
+ }
303
+ else {
304
+ connect(orderId, auth, key, getApi().getOptionsForKey(key) ?? {});
305
+ }
306
+ }
307
+ };
308
+ }
309
+ function disconnect(orderId, auth) {
310
+ if (reconnectTimeoutRef.current) {
311
+ clearTimeout(reconnectTimeoutRef.current);
312
+ reconnectTimeoutRef.current = null;
313
+ }
314
+ const key = getOrderTrackingCacheKey(orderId, auth);
315
+ const ws = wsCache.get(key)?.ws;
316
+ if (ws) {
317
+ pendingCleanups.set(key, setTimeout(() => {
318
+ pendingCleanups.delete(key);
319
+ if (wsCache.get(key)?.ws === ws) {
320
+ wsCache.delete(key);
321
+ ws.close();
322
+ }
323
+ }, 500));
324
+ }
325
+ }
326
+ return { connect, disconnect };
327
+ }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Shared types and helpers for order tracking (WebSocket + context).
3
+ * Used by orderTrackingConnection.ts and useOrderTracking.ts.
4
+ */
5
+ import type { SilentSwapClient } from '@silentswap/sdk';
6
+ export declare enum OutputStage {
7
+ NONE = "NONE",
8
+ INIT = "INIT",
9
+ FUNDED = "FUNDED",
10
+ REDEEMED = "REDEEMED",
11
+ IBC_SENT = "IBC_SENT",
12
+ IBC_RCVD = "IBC_RCVD",
13
+ BRIDGE_SENT = "BRIDGE_SENT",
14
+ BRIDGE_CFRM = "BRIDGE_CFRM",
15
+ BRIDGE_RCVD = "BRIDGE_RCVD",
16
+ SWAP_USDC_GAS = "SWAP_USDC_GAS",
17
+ SWAP_USDC_TRG = "SWAP_USDC_TRG",
18
+ LTRL_TRG_SENT = "LTRL_TRG_SENT",
19
+ LTRL_TRG_RCVD = "LTRL_TRG_RCVD",
20
+ SWAP_TRG_DST = "SWAP_TRG_DST",
21
+ XFER_TRG_DST = "XFER_TRG_DST",
22
+ REFUND_NATIVE = "REFUND_NATIVE",
23
+ FINALIZED = "FINALIZED"
24
+ }
25
+ export type OrderDeposit = {
26
+ amount: string;
27
+ timestamp: number;
28
+ duration: number;
29
+ orderId?: string;
30
+ tx?: string;
31
+ };
32
+ export type OrderTransactions = {
33
+ RECEIPT?: {
34
+ chain: string;
35
+ txId: string;
36
+ };
37
+ REFUND?: {
38
+ chain: string;
39
+ txId: string;
40
+ };
41
+ };
42
+ export type OutputStatus = {
43
+ index: number;
44
+ stage: OutputStage;
45
+ timestamp: number;
46
+ recipient?: string;
47
+ asset?: {
48
+ caip19: string;
49
+ amount: string;
50
+ decimals: number;
51
+ priceUsd?: number;
52
+ };
53
+ txs?: OrderTransactions;
54
+ };
55
+ export type IOutput = {
56
+ caip19: string;
57
+ amount: string;
58
+ decimals: number;
59
+ priceUsd?: number;
60
+ };
61
+ export type Outputs = Array<{
62
+ stage: OutputStage;
63
+ timestamp: number;
64
+ asset: string;
65
+ value: string;
66
+ recipient: string;
67
+ txs?: OrderTransactions;
68
+ output?: IOutput;
69
+ }>;
70
+ export type OrderStatus = {
71
+ priority?: string;
72
+ signer: string;
73
+ deposit?: OrderDeposit;
74
+ outputs: Outputs;
75
+ metadata?: {
76
+ sourceAsset?: {
77
+ caip19: string;
78
+ amount: string;
79
+ };
80
+ sourceSender?: {
81
+ contactId: string;
82
+ };
83
+ };
84
+ };
85
+ export type StatusUpdate = {
86
+ type: 'deposit';
87
+ data: OrderDeposit;
88
+ } | {
89
+ type: 'stage';
90
+ data: {
91
+ orderId: string;
92
+ index: number;
93
+ stage: OutputStage;
94
+ timestamp: number;
95
+ asset?: {
96
+ caip19: string;
97
+ amount: string;
98
+ decimals: number;
99
+ priceUsd?: number;
100
+ };
101
+ };
102
+ } | {
103
+ type: 'transaction';
104
+ data: {
105
+ orderId: string;
106
+ index: number;
107
+ chain: string;
108
+ txId: string;
109
+ kind: keyof OrderTransactions;
110
+ };
111
+ } | {
112
+ type: 'error';
113
+ data: {
114
+ orderId: string;
115
+ message: string;
116
+ index?: number;
117
+ };
118
+ };
119
+ export type JsonRpcError = {
120
+ code: number;
121
+ message: string;
122
+ data?: unknown;
123
+ };
124
+ export type OrderTrackingState = {
125
+ isConnected: boolean;
126
+ isLoading: boolean;
127
+ error: Error | null;
128
+ orderStatus: OrderStatus | null;
129
+ deposit: OrderDeposit | null;
130
+ outputs: OutputStatus[];
131
+ progresses: (number | undefined)[];
132
+ statusTexts: string[];
133
+ completedTimestamp: number | null;
134
+ isComplete: boolean;
135
+ };
136
+ export type OrderTrackingOptions = {
137
+ client?: SilentSwapClient;
138
+ onStatusUpdate?: (status: OrderStatus) => void;
139
+ onError?: (error: Error) => void;
140
+ onComplete?: () => void;
141
+ fetchAssetPrice?: (caip19: string) => Promise<number>;
142
+ };
143
+ export declare const DEFAULT_ORDER_TRACKING_STATE: OrderTrackingState;
144
+ export declare function getStatusTextFromStage(stage: OutputStage): string;
145
+ export declare function getProgressFromStage(stage: OutputStage): number;
146
+ export declare function getOrderTrackingCacheKey(orderId: string, auth: string): string;
147
+ export declare function hasFinalizedOutput(status: OrderStatus): boolean;
148
+ export declare function isFullOrderStatus(result: unknown): result is OrderStatus;
149
+ export declare function buildOrderTrackingWsUrl(client?: SilentSwapClient): string;