@shogun-sdk/swap 0.0.2-test.25 → 0.0.2-test.27

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/dist/react.cjs CHANGED
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
9
  var __export = (target, all) => {
7
10
  for (var name in all)
8
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,105 +18,45 @@ var __copyProps = (to, from, except, desc) => {
15
18
  }
16
19
  return to;
17
20
  };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
18
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
19
31
 
20
32
  // src/react/index.ts
21
33
  var react_exports = {};
22
34
  __export(react_exports, {
23
- ChainID: () => import_intents_sdk12.ChainID,
24
- isEvmChain: () => import_intents_sdk12.isEvmChain,
35
+ ChainId: () => ChainId,
36
+ OrderExecutionType: () => OrderExecutionType,
37
+ SupportedChains: () => SupportedChains,
38
+ SwapProvider: () => SwapProvider,
39
+ buildQuoteParams: () => buildQuoteParams,
40
+ isEvmChain: () => isEvmChain,
25
41
  useBalances: () => useBalances,
26
- useExecuteOrder: () => useExecuteOrder,
42
+ useExecuteTransaction: () => useExecuteTransaction,
43
+ useOrders: () => useOrders,
27
44
  useQuote: () => useQuote,
28
- useTokenList: () => useTokenList
45
+ useSwap: () => useSwap,
46
+ useTokenList: () => useTokenList,
47
+ useTokensData: () => useTokensData
29
48
  });
30
49
  module.exports = __toCommonJS(react_exports);
31
50
 
32
- // src/react/useTokenList.ts
51
+ // src/react/SwapProvider.tsx
33
52
  var import_react = require("react");
34
53
 
35
- // src/core/token-list.ts
36
- var import_intents_sdk = require("@shogun-sdk/intents-sdk");
37
- async function getTokenList(params) {
38
- return (0, import_intents_sdk.getTokenList)(params);
39
- }
40
-
41
- // src/react/useTokenList.ts
42
- var tokenCache = /* @__PURE__ */ new Map();
43
- function useTokenList(params) {
44
- const [data, setData] = (0, import_react.useState)(null);
45
- const [loading, setLoading] = (0, import_react.useState)(false);
46
- const [error, setError] = (0, import_react.useState)(null);
47
- const controllerRef = (0, import_react.useRef)(null);
48
- const debounceRef = (0, import_react.useRef)(null);
49
- const debounceMs = params.debounceMs ?? 250;
50
- const cacheKey = (0, import_react.useMemo)(() => {
51
- return JSON.stringify({
52
- q: params.q?.trim().toLowerCase() ?? "",
53
- networkId: params.networkId ?? "all",
54
- page: params.page ?? 1,
55
- limit: params.limit ?? 50
56
- });
57
- }, [params.q, params.networkId, params.page, params.limit]);
58
- async function fetchTokens(signal) {
59
- if (tokenCache.has(cacheKey)) {
60
- setData(tokenCache.get(cacheKey));
61
- setLoading(false);
62
- setError(null);
63
- return;
64
- }
65
- try {
66
- setLoading(true);
67
- const result = await getTokenList({ ...params, signal });
68
- tokenCache.set(cacheKey, result);
69
- setData(result);
70
- setError(null);
71
- } catch (err) {
72
- if (err.name !== "AbortError") {
73
- const e = err instanceof Error ? err : new Error("Unknown error while fetching tokens");
74
- setError(e);
75
- }
76
- } finally {
77
- setLoading(false);
78
- }
79
- }
80
- (0, import_react.useEffect)(() => {
81
- if (!params.q && !params.networkId) return;
82
- if (debounceRef.current) clearTimeout(debounceRef.current);
83
- if (controllerRef.current) controllerRef.current.abort();
84
- const controller = new AbortController();
85
- controllerRef.current = controller;
86
- debounceRef.current = setTimeout(() => {
87
- fetchTokens(controller.signal);
88
- }, debounceMs);
89
- return () => {
90
- controller.abort();
91
- if (debounceRef.current) clearTimeout(debounceRef.current);
92
- };
93
- }, [cacheKey, debounceMs]);
94
- return (0, import_react.useMemo)(
95
- () => ({
96
- /** Current fetched data (cached when possible) */
97
- data,
98
- /** Whether a request is in progress */
99
- loading,
100
- /** Error object if a request failed */
101
- error,
102
- /** Manually refetch the token list */
103
- refetch: () => fetchTokens(),
104
- /** Clear all cached token results (shared across hook instances) */
105
- clearCache: () => tokenCache.clear()
106
- }),
107
- [data, loading, error]
108
- );
109
- }
110
-
111
- // src/react/useExecuteOrder.ts
112
- var import_react2 = require("react");
54
+ // src/core/getQuote.ts
55
+ var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
56
+ var import_viem2 = require("viem");
113
57
 
114
- // src/core/executeOrder/execute.ts
115
- var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
116
- var import_viem5 = require("viem");
58
+ // src/core/execute/normalizeNative.ts
59
+ var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
117
60
 
118
61
  // src/utils/address.ts
119
62
  var import_viem = require("viem");
@@ -133,11 +76,25 @@ function normalizeEvmTokenAddress(address) {
133
76
  }
134
77
 
135
78
  // src/utils/chain.ts
136
- var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
137
- var SOLANA_CHAIN_ID = import_intents_sdk2.ChainID.Solana;
138
- var SupportedChains = [
79
+ var import_intents_sdk = require("@shogun-sdk/intents-sdk");
80
+ var SOLANA_CHAIN_ID = import_intents_sdk.ChainID.Solana;
81
+ var CURRENT_SUPPORTED = [
82
+ import_intents_sdk.ChainID.Solana,
83
+ import_intents_sdk.ChainID.BSC,
84
+ import_intents_sdk.ChainID.Base
85
+ ];
86
+ var ChainId = Object.entries(import_intents_sdk.ChainID).reduce(
87
+ (acc, [key, value]) => {
88
+ if (typeof value === "number" && CURRENT_SUPPORTED.includes(value)) {
89
+ acc[key] = value;
90
+ }
91
+ return acc;
92
+ },
93
+ {}
94
+ );
95
+ var SupportedChainsInternal = [
139
96
  {
140
- id: import_intents_sdk2.ChainID.Arbitrum,
97
+ id: import_intents_sdk.ChainID.Arbitrum,
141
98
  name: "Arbitrum",
142
99
  isEVM: true,
143
100
  wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -146,7 +103,7 @@ var SupportedChains = [
146
103
  tokenAddress: NATIVE_TOKEN.ETH
147
104
  },
148
105
  {
149
- id: import_intents_sdk2.ChainID.Optimism,
106
+ id: import_intents_sdk.ChainID.Optimism,
150
107
  name: "Optimism",
151
108
  isEVM: true,
152
109
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -155,7 +112,7 @@ var SupportedChains = [
155
112
  tokenAddress: NATIVE_TOKEN.ETH
156
113
  },
157
114
  {
158
- id: import_intents_sdk2.ChainID.Base,
115
+ id: import_intents_sdk.ChainID.Base,
159
116
  name: "Base",
160
117
  isEVM: true,
161
118
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -164,7 +121,7 @@ var SupportedChains = [
164
121
  tokenAddress: NATIVE_TOKEN.ETH
165
122
  },
166
123
  {
167
- id: import_intents_sdk2.ChainID.Hyperliquid,
124
+ id: import_intents_sdk.ChainID.Hyperliquid,
168
125
  name: "Hyperliquid",
169
126
  isEVM: true,
170
127
  wrapped: "0x5555555555555555555555555555555555555555",
@@ -173,7 +130,7 @@ var SupportedChains = [
173
130
  tokenAddress: NATIVE_TOKEN.ETH
174
131
  },
175
132
  {
176
- id: import_intents_sdk2.ChainID.BSC,
133
+ id: import_intents_sdk.ChainID.BSC,
177
134
  name: "BSC",
178
135
  isEVM: true,
179
136
  wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
@@ -191,6 +148,10 @@ var SupportedChains = [
191
148
  tokenAddress: NATIVE_TOKEN.SOL
192
149
  }
193
150
  ];
151
+ var SupportedChains = SupportedChainsInternal.filter(
152
+ (c) => CURRENT_SUPPORTED.includes(c.id)
153
+ );
154
+ var isEvmChain = import_intents_sdk.isEvmChain;
194
155
 
195
156
  // src/utils/viem.ts
196
157
  function isViemWalletClient(wallet) {
@@ -218,10 +179,198 @@ function serializeBigIntsToStrings(obj) {
218
179
  return obj;
219
180
  }
220
181
 
182
+ // src/core/execute/normalizeNative.ts
183
+ function normalizeNative(chainId, address) {
184
+ if ((0, import_intents_sdk2.isEvmChain)(chainId) && isNativeAddress(address)) {
185
+ const chain = SupportedChains.find((c) => c.id === chainId);
186
+ if (!chain?.wrapped)
187
+ throw new Error(`Wrapped token not found for chainId ${chainId}`);
188
+ return chain.wrapped;
189
+ }
190
+ return address;
191
+ }
192
+
193
+ // src/core/getQuote.ts
194
+ async function getQuote(params) {
195
+ const amount = BigInt(params.amount);
196
+ if (!params.tokenIn?.address || !params.tokenOut?.address) {
197
+ throw new Error("Both tokenIn and tokenOut must include an address.");
198
+ }
199
+ if (!params.sourceChainId || !params.destChainId) {
200
+ throw new Error("Both sourceChainId and destChainId are required.");
201
+ }
202
+ if (amount <= 0n) {
203
+ throw new Error("Amount must be greater than 0.");
204
+ }
205
+ const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
206
+ const data = await import_intents_sdk3.QuoteProvider.getQuote({
207
+ sourceChainId: params.sourceChainId,
208
+ destChainId: params.destChainId,
209
+ tokenIn: normalizedTokenIn,
210
+ tokenOut: params.tokenOut.address,
211
+ amount
212
+ });
213
+ const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
214
+ let warning;
215
+ if (slippagePercent > 10) {
216
+ warning = `\u26A0\uFE0F High slippage tolerance (${slippagePercent.toFixed(2)}%) \u2014 price may vary significantly.`;
217
+ }
218
+ const estimatedAmountOut = BigInt(data.estimatedAmountOut);
219
+ const slippageBps = BigInt(Math.round(slippagePercent * 100));
220
+ const estimatedAmountOutAfterSlippage = estimatedAmountOut * (10000n - slippageBps) / 10000n;
221
+ const pricePerTokenOutInUsd = data.estimatedAmountOutUsd / Number(data.estimatedAmountOut);
222
+ const amountOutUsdAfterSlippage = Number(estimatedAmountOutAfterSlippage) * pricePerTokenOutInUsd;
223
+ const minStablecoinsAmountValue = BigInt(data.estimatedAmountInAsMinStablecoinAmount);
224
+ const minStablecoinsAmountAfterSlippage = minStablecoinsAmountValue * (10000n - slippageBps) / 10000n;
225
+ const pricePerInputToken = estimatedAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / BigInt(params.amount);
226
+ return {
227
+ amountOut: estimatedAmountOutAfterSlippage,
228
+ amountOutUsd: amountOutUsdAfterSlippage,
229
+ amountInUsd: data.amountInUsd,
230
+ // Input USD stays the same
231
+ minStablecoinsAmount: minStablecoinsAmountAfterSlippage,
232
+ tokenIn: {
233
+ address: params.tokenIn.address,
234
+ decimals: params.tokenIn.decimals ?? 18,
235
+ chainId: params.sourceChainId
236
+ },
237
+ tokenOut: {
238
+ address: params.tokenOut.address,
239
+ decimals: params.tokenOut.decimals ?? 18,
240
+ chainId: params.destChainId
241
+ },
242
+ amountIn: BigInt(params.amount),
243
+ pricePerInputToken,
244
+ slippage: slippagePercent,
245
+ internal: {
246
+ ...data,
247
+ estimatedAmountOutReduced: estimatedAmountOutAfterSlippage,
248
+ estimatedAmountOutUsdReduced: amountOutUsdAfterSlippage
249
+ },
250
+ warning
251
+ };
252
+ }
253
+ function buildQuoteParams({
254
+ tokenIn,
255
+ tokenOut,
256
+ sourceChainId,
257
+ destChainId,
258
+ amount,
259
+ slippage
260
+ }) {
261
+ return {
262
+ tokenIn,
263
+ tokenOut,
264
+ sourceChainId,
265
+ destChainId,
266
+ amount: (0, import_viem2.parseUnits)(amount.toString(), tokenIn.decimals ?? 18).toString(),
267
+ slippage
268
+ };
269
+ }
270
+
271
+ // src/core/getBalances.ts
272
+ var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
273
+ async function getBalances(params, options) {
274
+ const { addresses, cursorEvm, cursorSvm } = params;
275
+ const { signal } = options ?? {};
276
+ if (!addresses?.evm && !addresses?.svm) {
277
+ throw new Error("At least one address (EVM or SVM) must be provided.");
278
+ }
279
+ const payload = JSON.stringify({
280
+ addresses,
281
+ cursorEvm,
282
+ cursorSvm
283
+ });
284
+ const start = performance.now();
285
+ const response = await fetch(`${import_intents_sdk4.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
286
+ method: "POST",
287
+ headers: {
288
+ accept: "application/json",
289
+ "Content-Type": "application/json"
290
+ },
291
+ body: payload,
292
+ signal
293
+ }).catch((err) => {
294
+ if (err.name === "AbortError") {
295
+ throw new Error("Balance request was cancelled.");
296
+ }
297
+ throw err;
298
+ });
299
+ if (!response.ok) {
300
+ const text = await response.text().catch(() => "");
301
+ throw new Error(`Failed to fetch balances: ${response.status} ${text}`);
302
+ }
303
+ const data = await response.json().catch(() => {
304
+ throw new Error("Invalid JSON response from balances API.");
305
+ });
306
+ const duration = (performance.now() - start).toFixed(1);
307
+ if (process.env.NODE_ENV !== "production") {
308
+ console.debug(`[Shogun SDK] Fetched balances in ${duration}ms`);
309
+ }
310
+ const evmItems = data.evm?.items ?? [];
311
+ const svmItems = data.svm?.items ?? [];
312
+ const combined = [...evmItems, ...svmItems];
313
+ const filtered = combined.filter(
314
+ (b) => CURRENT_SUPPORTED.includes(b.chainId)
315
+ );
316
+ return {
317
+ results: filtered,
318
+ nextCursorEvm: data.evm?.cursor ?? null,
319
+ nextCursorSvm: data.svm?.cursor ?? null
320
+ };
321
+ }
322
+
323
+ // src/core/token-list.ts
324
+ var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
325
+ async function getTokenList(params) {
326
+ const url = new URL(`${import_intents_sdk5.TOKEN_SEARCH_API_BASE_URL}/tokens/search`);
327
+ if (params.q) url.searchParams.append("q", params.q);
328
+ if (params.networkId) url.searchParams.append("networkId", String(params.networkId));
329
+ if (params.page) url.searchParams.append("page", String(params.page));
330
+ if (params.limit) url.searchParams.append("limit", String(params.limit));
331
+ const res = await fetch(url.toString(), {
332
+ signal: params.signal
333
+ });
334
+ if (!res.ok) {
335
+ throw new Error(`Failed to fetch tokens: ${res.status} ${res.statusText}`);
336
+ }
337
+ const data = await res.json();
338
+ const filteredResults = data.results.filter(
339
+ (token) => CURRENT_SUPPORTED.includes(token.chainId)
340
+ );
341
+ return {
342
+ ...data,
343
+ results: filteredResults,
344
+ count: filteredResults.length
345
+ };
346
+ }
347
+
348
+ // src/core/token.ts
349
+ var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
350
+ async function getTokensData(addresses) {
351
+ if (!addresses?.length) return [];
352
+ const response = await fetch(`${import_intents_sdk6.TOKEN_SEARCH_API_BASE_URL}/tokens/tokens`, {
353
+ method: "POST",
354
+ headers: {
355
+ "Content-Type": "application/json",
356
+ accept: "*/*"
357
+ },
358
+ body: JSON.stringify({ addresses })
359
+ });
360
+ if (!response.ok) {
361
+ throw new Error(`Failed to fetch token data: ${response.statusText}`);
362
+ }
363
+ const data = await response.json();
364
+ const filtered = data.filter((t) => CURRENT_SUPPORTED.includes(Number(t.chainId)));
365
+ return filtered;
366
+ }
367
+
368
+ // src/core/execute/execute.ts
369
+ var import_intents_sdk12 = require("@shogun-sdk/intents-sdk");
370
+ var import_viem7 = require("viem");
371
+
221
372
  // src/wallet-adapter/evm-wallet-adapter/adapter.ts
222
- var import_ethers = require("ethers/lib/ethers.js");
223
- var import_utils = require("ethers/lib/utils.js");
224
- var import_viem2 = require("viem");
373
+ var import_viem3 = require("viem");
225
374
  function isEVMTransaction(tx) {
226
375
  return typeof tx.from === "string";
227
376
  }
@@ -287,7 +436,7 @@ var adaptViemWallet = (wallet) => {
287
436
  functionName,
288
437
  args = []
289
438
  }) => {
290
- const publicClient = wallet.extend(import_viem2.publicActions);
439
+ const publicClient = wallet.extend(import_viem3.publicActions);
291
440
  return await publicClient.readContract({
292
441
  address: address2,
293
442
  abi,
@@ -297,7 +446,7 @@ var adaptViemWallet = (wallet) => {
297
446
  };
298
447
  return {
299
448
  vmType: "EVM" /* EVM */,
300
- transport: (0, import_viem2.custom)(wallet.transport),
449
+ transport: (0, import_viem3.custom)(wallet.transport),
301
450
  getChainId: async () => wallet.getChainId(),
302
451
  address,
303
452
  sendTransaction,
@@ -307,23 +456,11 @@ var adaptViemWallet = (wallet) => {
307
456
  };
308
457
  };
309
458
 
310
- // src/core/executeOrder/handleEvmExecution.ts
311
- var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
312
- var import_viem4 = require("viem");
313
-
314
- // src/core/executeOrder/normalizeNative.ts
315
- var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
316
- function normalizeNative(chainId, address) {
317
- if ((0, import_intents_sdk3.isEvmChain)(chainId) && isNativeAddress(address)) {
318
- const chain = SupportedChains.find((c) => c.id === chainId);
319
- if (!chain?.wrapped)
320
- throw new Error(`Wrapped token not found for chainId ${chainId}`);
321
- return chain.wrapped;
322
- }
323
- return address;
324
- }
459
+ // src/core/execute/handleEvmExecution.ts
460
+ var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
461
+ var import_viem6 = require("viem");
325
462
 
326
- // src/core/executeOrder/stageMessages.ts
463
+ // src/core/execute/stageMessages.ts
327
464
  var DEFAULT_STAGE_MESSAGES = {
328
465
  processing: "Preparing transaction for execution",
329
466
  approving: "Approving token allowance",
@@ -332,33 +469,57 @@ var DEFAULT_STAGE_MESSAGES = {
332
469
  submitting: "Submitting transaction",
333
470
  initiated: "Transaction initiated.",
334
471
  success: "Transaction Executed successfully",
472
+ success_limit: "Limit order has been submitted successfully.",
335
473
  shogun_processing: "Shogun is processing your transaction",
336
474
  error: "Transaction failed during submission"
337
475
  };
338
476
 
339
- // src/core/executeOrder/buildOrder.ts
340
- var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
477
+ // src/core/execute/buildOrder.ts
478
+ var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
479
+ var import_viem4 = require("viem");
480
+
481
+ // src/utils/order.ts
482
+ var OrderExecutionType = /* @__PURE__ */ ((OrderExecutionType2) => {
483
+ OrderExecutionType2["LIMIT"] = "limit";
484
+ OrderExecutionType2["MARKET"] = "market";
485
+ return OrderExecutionType2;
486
+ })(OrderExecutionType || {});
487
+
488
+ // src/core/execute/buildOrder.ts
341
489
  async function buildOrder({
342
490
  quote,
343
491
  accountAddress,
344
492
  destination,
345
493
  deadline,
346
- isSingleChain
494
+ isSingleChain,
495
+ orderType,
496
+ options
347
497
  }) {
348
498
  const { tokenIn, tokenOut } = quote;
499
+ let amountOutMin = BigInt(quote.internal.estimatedAmountOutReduced);
500
+ if (orderType === "limit" /* LIMIT */ && options && "executionPrice" in options) {
501
+ const executionPrice = Number(options.executionPrice);
502
+ if (Number.isFinite(executionPrice) && executionPrice > 0) {
503
+ const decimalsIn = tokenIn.decimals ?? 18;
504
+ const decimalsOut = tokenOut.decimals ?? 18;
505
+ const formattedAmountIn = Number((0, import_viem4.formatUnits)(BigInt(quote.amountIn.toString()), decimalsIn));
506
+ const rawAmountOut = formattedAmountIn * executionPrice;
507
+ amountOutMin = (0, import_viem4.parseUnits)(rawAmountOut.toString(), decimalsOut);
508
+ }
509
+ }
349
510
  if (isSingleChain) {
350
- return await import_intents_sdk4.SingleChainOrder.create({
511
+ return await import_intents_sdk7.SingleChainOrder.create({
351
512
  user: accountAddress,
352
513
  chainId: tokenIn.chainId,
353
514
  tokenIn: tokenIn.address,
354
515
  tokenOut: tokenOut.address,
355
516
  amountIn: quote.amountIn,
356
- amountOutMin: quote.internal.estimatedAmountOutReduced,
517
+ amountOutMin,
357
518
  deadline,
358
519
  destinationAddress: destination
359
520
  });
360
521
  }
361
- return await import_intents_sdk4.CrossChainOrder.create({
522
+ return await import_intents_sdk7.CrossChainOrder.create({
362
523
  user: accountAddress,
363
524
  sourceChainId: tokenIn.chainId,
364
525
  sourceTokenAddress: tokenIn.address,
@@ -367,13 +528,13 @@ async function buildOrder({
367
528
  destinationTokenAddress: tokenOut.address,
368
529
  destinationAddress: destination,
369
530
  deadline,
370
- destinationTokenMinAmount: quote.internal.estimatedAmountOutReduced,
531
+ destinationTokenMinAmount: amountOutMin,
371
532
  minStablecoinAmount: quote.minStablecoinsAmount
372
533
  });
373
534
  }
374
535
 
375
536
  // src/utils/pollOrderStatus.ts
376
- var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
537
+ var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
377
538
  async function pollOrderStatus(address, orderId, options = {}) {
378
539
  const { intervalMs = 2e3, timeoutMs = 3e5 } = options;
379
540
  const startTime = Date.now();
@@ -386,7 +547,7 @@ async function pollOrderStatus(address, orderId, options = {}) {
386
547
  else if (isSuiAddress) queryParam = `suiWallets=${address}`;
387
548
  else if (isSolanaAddress) queryParam = `solanaWallets=${address}`;
388
549
  else throw new Error(`Unrecognized wallet address format: ${address}`);
389
- const queryUrl = `${import_intents_sdk5.AUCTIONEER_URL}/user_intent?${queryParam}`;
550
+ const queryUrl = `${import_intents_sdk8.AUCTIONEER_URL}/user_intent?${queryParam}`;
390
551
  return new Promise((resolve, reject) => {
391
552
  const pollInterval = setInterval(async () => {
392
553
  try {
@@ -438,7 +599,7 @@ async function pollOrderStatus(address, orderId, options = {}) {
438
599
  });
439
600
  }
440
601
 
441
- // src/core/executeOrder/handleOrderPollingResult.ts
602
+ // src/core/execute/handleOrderPollingResult.ts
442
603
  async function handleOrderPollingResult({
443
604
  status,
444
605
  orderId,
@@ -476,9 +637,9 @@ async function handleOrderPollingResult({
476
637
  };
477
638
  }
478
639
 
479
- // src/core/executeOrder/ensurePermit2Allowance.ts
480
- var import_viem3 = require("viem");
481
- var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
640
+ // src/core/execute/ensurePermit2Allowance.ts
641
+ var import_viem5 = require("viem");
642
+ var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
482
643
  async function ensurePermit2Allowance({
483
644
  chainId,
484
645
  tokenIn,
@@ -487,7 +648,7 @@ async function ensurePermit2Allowance({
487
648
  requiredAmount,
488
649
  increaseByDelta = false
489
650
  }) {
490
- const spender = import_intents_sdk6.PERMIT2_ADDRESS[chainId];
651
+ const spender = import_intents_sdk9.PERMIT2_ADDRESS[chainId];
491
652
  let currentAllowance = 0n;
492
653
  try {
493
654
  if (!wallet.readContract) {
@@ -495,22 +656,22 @@ async function ensurePermit2Allowance({
495
656
  }
496
657
  currentAllowance = await wallet.readContract({
497
658
  address: tokenIn,
498
- abi: import_viem3.erc20Abi,
659
+ abi: import_viem5.erc20Abi,
499
660
  functionName: "allowance",
500
661
  args: [accountAddress, spender]
501
662
  });
502
663
  } catch (error) {
503
664
  console.warn(`[Permit2] Failed to read allowance for ${tokenIn}`, error);
504
665
  }
505
- const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount : import_viem3.maxUint256;
666
+ const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount : import_viem5.maxUint256;
506
667
  console.debug(
507
668
  `[Permit2] Approving ${approvalAmount} for ${tokenIn} (current: ${currentAllowance}, required: ${requiredAmount})`
508
669
  );
509
670
  await wallet.sendTransaction({
510
671
  to: tokenIn,
511
672
  from: accountAddress,
512
- data: (0, import_viem3.encodeFunctionData)({
513
- abi: import_viem3.erc20Abi,
673
+ data: (0, import_viem5.encodeFunctionData)({
674
+ abi: import_viem5.erc20Abi,
514
675
  functionName: "approve",
515
676
  args: [spender, approvalAmount]
516
677
  }),
@@ -521,7 +682,7 @@ async function ensurePermit2Allowance({
521
682
  );
522
683
  }
523
684
 
524
- // src/core/executeOrder/handleEvmExecution.ts
685
+ // src/core/execute/handleEvmExecution.ts
525
686
  async function handleEvmExecution({
526
687
  recipientAddress,
527
688
  quote,
@@ -529,19 +690,22 @@ async function handleEvmExecution({
529
690
  accountAddress,
530
691
  wallet,
531
692
  isSingleChain,
532
- deadline,
533
- update
693
+ update,
694
+ orderType,
695
+ options
534
696
  }) {
535
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
697
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
698
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
536
699
  await wallet.switchChain(chainId);
537
700
  const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
538
701
  quote.tokenOut.address = normalizeEvmTokenAddress(quote.tokenOut.address);
539
702
  const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
540
703
  update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
541
704
  if (shouldWrapNative) {
705
+ quote.tokenIn.address === tokenIn;
542
706
  await wallet.sendTransaction({
543
707
  to: tokenIn,
544
- data: (0, import_viem4.encodeFunctionData)({
708
+ data: (0, import_viem6.encodeFunctionData)({
545
709
  abi: [{ type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] }],
546
710
  functionName: "deposit",
547
711
  args: []
@@ -565,11 +729,13 @@ async function handleEvmExecution({
565
729
  accountAddress,
566
730
  destination,
567
731
  deadline,
568
- isSingleChain
732
+ isSingleChain,
733
+ orderType,
734
+ options
569
735
  });
570
736
  console.debug(`order`, order);
571
737
  update("processing", messageFor("signing"));
572
- const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk7.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk7.getEVMCrossChainOrderTypedData)(order);
738
+ const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk10.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk10.getEVMCrossChainOrderTypedData)(order);
573
739
  const typedData = serializeBigIntsToStrings(orderTypedData);
574
740
  if (!wallet.signTypedData) {
575
741
  throw new Error("Wallet does not support EIP-712 signing");
@@ -589,18 +755,29 @@ async function handleEvmExecution({
589
755
  update("initiated", messageFor("initiated"));
590
756
  const { intentId: orderId } = res.data;
591
757
  update("initiated", messageFor("shogun_processing"));
592
- const status = await pollOrderStatus(accountAddress, orderId);
593
- return await handleOrderPollingResult({
594
- status,
595
- orderId,
596
- chainId,
597
- update,
598
- messageFor
599
- });
758
+ if (orderType === "limit" /* LIMIT */) {
759
+ update("success", messageFor("success_limit"));
760
+ return {
761
+ status: true,
762
+ orderId,
763
+ chainId,
764
+ finalStatus: "OrderPlaced",
765
+ stage: "success"
766
+ };
767
+ } else {
768
+ const status = await pollOrderStatus(accountAddress, orderId);
769
+ return await handleOrderPollingResult({
770
+ status,
771
+ orderId,
772
+ chainId,
773
+ update,
774
+ messageFor
775
+ });
776
+ }
600
777
  }
601
778
 
602
- // src/core/executeOrder/handleSolanaExecution.ts
603
- var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
779
+ // src/core/execute/handleSolanaExecution.ts
780
+ var import_intents_sdk11 = require("@shogun-sdk/intents-sdk");
604
781
  var import_web3 = require("@solana/web3.js");
605
782
  async function handleSolanaExecution({
606
783
  recipientAddress,
@@ -609,12 +786,14 @@ async function handleSolanaExecution({
609
786
  isSingleChain,
610
787
  update,
611
788
  accountAddress,
612
- deadline
789
+ orderType,
790
+ options
613
791
  }) {
614
792
  if (!wallet.rpcUrl) {
615
793
  throw new Error("Solana wallet is missing rpcUrl");
616
794
  }
617
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
795
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
796
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
618
797
  update("processing", messageFor("processing"));
619
798
  const destination = recipientAddress ?? accountAddress;
620
799
  const order = await buildOrder({
@@ -622,7 +801,9 @@ async function handleSolanaExecution({
622
801
  accountAddress,
623
802
  destination,
624
803
  deadline,
625
- isSingleChain
804
+ isSingleChain,
805
+ orderType,
806
+ options
626
807
  });
627
808
  const txData = await getSolanaOrderInstructions({
628
809
  order,
@@ -642,16 +823,27 @@ async function handleSolanaExecution({
642
823
  throw new Error("Auctioneer submission failed");
643
824
  }
644
825
  update("initiated", messageFor("initiated"));
645
- const { jwt, intentId: orderId } = response.data;
826
+ const { intentId: orderId } = response.data;
646
827
  update("initiated", messageFor("shogun_processing"));
647
- const status = await pollOrderStatus(jwt, orderId);
648
- return await handleOrderPollingResult({
649
- status,
650
- orderId,
651
- chainId: SOLANA_CHAIN_ID,
652
- update,
653
- messageFor
654
- });
828
+ if (orderType === "limit" /* LIMIT */) {
829
+ update("success", messageFor("success_limit"));
830
+ return {
831
+ status: true,
832
+ orderId,
833
+ chainId: SOLANA_CHAIN_ID,
834
+ finalStatus: "OrderPlaced",
835
+ stage: "success"
836
+ };
837
+ } else {
838
+ const status = await pollOrderStatus(accountAddress, orderId);
839
+ return await handleOrderPollingResult({
840
+ status,
841
+ orderId,
842
+ chainId: SOLANA_CHAIN_ID,
843
+ update,
844
+ messageFor
845
+ });
846
+ }
655
847
  }
656
848
  async function getSolanaOrderInstructions({
657
849
  order,
@@ -659,11 +851,11 @@ async function getSolanaOrderInstructions({
659
851
  rpcUrl
660
852
  }) {
661
853
  if (isSingleChain) {
662
- return await (0, import_intents_sdk8.getSolanaSingleChainOrderInstructions)(order, {
854
+ return await (0, import_intents_sdk11.getSolanaSingleChainOrderInstructions)(order, {
663
855
  rpcUrl
664
856
  });
665
857
  }
666
- return await (0, import_intents_sdk8.getSolanaCrossChainOrderInstructions)(order, {
858
+ return await (0, import_intents_sdk11.getSolanaCrossChainOrderInstructions)(order, {
667
859
  rpcUrl
668
860
  });
669
861
  }
@@ -684,13 +876,14 @@ async function submitToAuctioneer({
684
876
  });
685
877
  }
686
878
 
687
- // src/core/executeOrder/execute.ts
879
+ // src/core/execute/execute.ts
688
880
  async function executeOrder({
689
881
  quote,
690
882
  accountAddress,
691
883
  recipientAddress,
692
884
  wallet,
693
885
  onStatus,
886
+ orderType = "market" /* MARKET */,
694
887
  options = {}
695
888
  }) {
696
889
  const isDev = process.env.NODE_ENV !== "production";
@@ -703,21 +896,31 @@ async function executeOrder({
703
896
  onStatus?.(stage, message ?? messageFor(stage));
704
897
  };
705
898
  try {
706
- const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
707
899
  log("Starting execution:", {
708
900
  accountAddress,
709
901
  recipientAddress,
710
- deadline,
711
902
  tokenIn: quote?.tokenIn,
712
903
  tokenOut: quote?.tokenOut
713
904
  });
714
905
  const adapter = normalizeWallet(wallet);
715
906
  if (!adapter) throw new Error("No wallet provided");
716
907
  const { tokenIn, tokenOut } = quote;
908
+ const srcChain = Number(tokenIn.chainId);
909
+ const destChain = Number(tokenOut.chainId);
910
+ if (!CURRENT_SUPPORTED.includes(srcChain) || !CURRENT_SUPPORTED.includes(destChain)) {
911
+ const unsupportedChains = [
912
+ !CURRENT_SUPPORTED.includes(srcChain) ? srcChain : null,
913
+ !CURRENT_SUPPORTED.includes(destChain) ? destChain : null
914
+ ].filter(Boolean).join(", ");
915
+ const errorMsg = `Unsupported chain(s): ${unsupportedChains}`;
916
+ update("error", errorMsg);
917
+ log("Error:", errorMsg);
918
+ throw new Error(errorMsg);
919
+ }
717
920
  const isSingleChain = tokenIn.chainId === tokenOut.chainId;
718
921
  const chainId = Number(tokenIn.chainId);
719
922
  update("processing");
720
- if ((0, import_intents_sdk9.isEvmChain)(chainId)) {
923
+ if ((0, import_intents_sdk12.isEvmChain)(chainId)) {
721
924
  log("Detected EVM chain:", chainId);
722
925
  const result = await handleEvmExecution({
723
926
  recipientAddress,
@@ -726,13 +929,14 @@ async function executeOrder({
726
929
  accountAddress,
727
930
  wallet: adapter,
728
931
  isSingleChain,
729
- deadline,
730
- update
932
+ update,
933
+ orderType,
934
+ options
731
935
  });
732
936
  log("EVM execution result:", result);
733
937
  return result;
734
938
  }
735
- if (chainId === import_intents_sdk9.ChainID.Solana) {
939
+ if (chainId === import_intents_sdk12.ChainID.Solana) {
736
940
  log("Detected Solana chain");
737
941
  const result = await handleSolanaExecution({
738
942
  recipientAddress,
@@ -740,8 +944,9 @@ async function executeOrder({
740
944
  accountAddress,
741
945
  wallet: adapter,
742
946
  isSingleChain,
743
- deadline,
744
- update
947
+ update,
948
+ orderType,
949
+ options
745
950
  });
746
951
  log("Solana execution result:", result);
747
952
  return result;
@@ -751,8 +956,13 @@ async function executeOrder({
751
956
  log("Error:", unsupported);
752
957
  return { status: false, message: unsupported, stage: "error" };
753
958
  } catch (error) {
754
- const message = error instanceof import_viem5.BaseError ? error.shortMessage : error instanceof Error ? error.message : String(error);
755
- log("Execution failed:", { message, error });
959
+ let message = "An unknown error occurred";
960
+ if (error && typeof error === "object") {
961
+ const err = error;
962
+ message = err.details ?? err.message ?? message;
963
+ } else if (typeof error === "string") {
964
+ message = error;
965
+ }
756
966
  update("error", message);
757
967
  return { status: false, message, stage: "error" };
758
968
  }
@@ -763,345 +973,590 @@ function normalizeWallet(wallet) {
763
973
  return wallet;
764
974
  }
765
975
 
766
- // src/react/useExecuteOrder.ts
767
- function useExecuteOrder() {
768
- const [status, setStatus] = (0, import_react2.useState)("processing");
769
- const [message, setMessage] = (0, import_react2.useState)(null);
770
- const [loading, setLoading] = (0, import_react2.useState)(false);
771
- const [data, setData] = (0, import_react2.useState)(null);
772
- const [error, setError] = (0, import_react2.useState)(null);
773
- const isMounted = (0, import_react2.useRef)(true);
976
+ // src/core/orders/getOrders.ts
977
+ var import_intents_sdk13 = require("@shogun-sdk/intents-sdk");
978
+ async function getOrders({
979
+ evmAddress,
980
+ solAddress
981
+ }) {
982
+ if (!evmAddress && !solAddress) {
983
+ throw new Error("At least one wallet address (EVM, Solana) must be provided.");
984
+ }
985
+ const orders = await (0, import_intents_sdk13.fetchUserOrders)(evmAddress, solAddress);
986
+ return orders;
987
+ }
988
+
989
+ // src/core/client.ts
990
+ var SwapSDK = class {
991
+ constructor(config) {
992
+ __publicField(this, "apiKey");
993
+ /**
994
+ * Fetches metadata for one or more tokens from the Shogun Token Search API.
995
+ *
996
+ * ---
997
+ * ### Overview
998
+ * `getTokensData` retrieves normalized token information — such as symbol, name,
999
+ * decimals, logo URI, and verified status — for a given list of token addresses.
1000
+ *
1001
+ * It supports both **EVM** and **SVM (Solana)** tokens, returning metadata from
1002
+ * Shogun’s unified token registry.
1003
+ *
1004
+ * ---
1005
+ * @example
1006
+ * ```ts
1007
+ * const tokens = await getTokensData([
1008
+ * "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
1009
+ * "So11111111111111111111111111111111111111112", // SOL
1010
+ * ]);
1011
+ *
1012
+ * console.log(tokens);
1013
+ * [
1014
+ * { symbol: "USDC", name: "USD Coin", chainId: 1, decimals: 6, ... },
1015
+ * { symbol: "SOL", name: "Solana", chainId: 101, decimals: 9, ... }
1016
+ * ]
1017
+ * ```
1018
+ *
1019
+ * @param addresses - An array of token addresses (EVM or SVM) to fetch metadata for.
1020
+ * @returns A promise resolving to an array of {@link TokenInfo} objects.
1021
+ *
1022
+ * @throws Will throw an error if the network request fails or the API responds with a non-OK status.
1023
+ */
1024
+ __publicField(this, "getTokensData", getTokensData.bind(this));
1025
+ if (!config.apiKey) {
1026
+ throw new Error("SwapSDK: Missing API key");
1027
+ }
1028
+ this.apiKey = config.apiKey;
1029
+ if (this.apiKey) void this.apiKey;
1030
+ }
1031
+ /**
1032
+ * Retrieves a swap quote for the given input and output tokens.
1033
+ *
1034
+ * @param params - Quote parameters including source/destination tokens and amount.
1035
+ * @returns A normalized `SwapQuoteResponse` containing output amount, route, and metadata.
1036
+ */
1037
+ async getQuote(params) {
1038
+ return getQuote(params);
1039
+ }
1040
+ /**
1041
+ * Fetches token balances for the specified user wallet(s).
1042
+ *
1043
+ * Supports both EVM and SVM (Solana) wallet addresses.
1044
+ *
1045
+ * @param params - Wallet address and optional chain filters.
1046
+ * @param options - Optional abort signal for cancellation.
1047
+ * @returns A unified balance response with per-chain token details.
1048
+ */
1049
+ async getBalances(params, options) {
1050
+ return getBalances(params, options);
1051
+ }
1052
+ /**
1053
+ * Retrieves a list of verified tokens based on search query or chain filter.
1054
+ *
1055
+ * @param params - Search parameters (query, chain ID, pagination options).
1056
+ * @returns Paginated `TokenSearchResponse` containing token metadata.
1057
+ */
1058
+ async getTokenList(params) {
1059
+ return getTokenList(params);
1060
+ }
1061
+ /**
1062
+ * Executes a prepared swap quote using the provided wallet and configuration.
1063
+ *
1064
+ * Handles:
1065
+ * - Token approval (if required)
1066
+ * - Transaction signing and broadcasting
1067
+ * - Confirmation polling and stage-based status updates
1068
+ *
1069
+ * Supports both:
1070
+ * - Market orders (with optional deadline)
1071
+ * - Limit orders (requires executionPrice and deadline)
1072
+ *
1073
+ * @param quote - The swap quote to execute, containing route and metadata.
1074
+ * @param accountAddress - The user's wallet address executing the swap.
1075
+ * @param recipientAddress - Optional recipient address for the output tokens (defaults to sender).
1076
+ * @param wallet - Adapted wallet instance (EVM/Solana) or a standard Viem `WalletClient`.
1077
+ * @param onStatus - Optional callback for receiving execution stage updates and messages.
1078
+ * @param orderType - Defines whether this is a market or limit order.
1079
+ * @param options - Execution parameters (different per order type).
1080
+ *
1081
+ * @returns A finalized execution result containing transaction hash, status, and any returned data.
1082
+ *
1083
+ * @example
1084
+ * ```ts
1085
+ * * Market order
1086
+ * const result = await sdk.executeTransaction({
1087
+ * quote,
1088
+ * accountAddress: "0x123...",
1089
+ * wallet,
1090
+ * orderType: OrderExecutionType.MARKET,
1091
+ * options: { deadline: 1800 },
1092
+ * onStatus: (stage, msg) => console.log(stage, msg),
1093
+ * });
1094
+ *
1095
+ * * Limit order
1096
+ * const result = await sdk.executeTransaction({
1097
+ * quote,
1098
+ * accountAddress: "0x123...",
1099
+ * wallet,
1100
+ * orderType: OrderExecutionType.LIMIT,
1101
+ * options: { executionPrice: "0.0021", deadline: 3600 },
1102
+ * });
1103
+ * ```
1104
+ */
1105
+ async executeTransaction({
1106
+ quote,
1107
+ accountAddress,
1108
+ recipientAddress,
1109
+ wallet,
1110
+ onStatus,
1111
+ orderType,
1112
+ options
1113
+ }) {
1114
+ return executeOrder({
1115
+ quote,
1116
+ wallet,
1117
+ accountAddress,
1118
+ recipientAddress,
1119
+ onStatus,
1120
+ orderType,
1121
+ options
1122
+ });
1123
+ }
1124
+ /**
1125
+ * Fetches all user orders (Market, Limit, Cross-chain) for connected wallets.
1126
+ *
1127
+ * ---
1128
+ * ### Overview
1129
+ * Retrieves both **single-chain** and **cross-chain** orders from the Shogun Intents API.
1130
+ * Works across EVM, Solana
1131
+ *
1132
+ * ---
1133
+ * @example
1134
+ * ```ts
1135
+ * const orders = await sdk.getOrders({
1136
+ * evmAddress: "0x123...",
1137
+ * solAddress: "9d12hF...abc",
1138
+ * });
1139
+ *
1140
+ * console.log(orders.singleChainLimitOrders);
1141
+ * ```
1142
+ *
1143
+ * @param params - Wallet addresses to fetch orders for (EVM, Solana).
1144
+ * @returns A structured {@link ApiUserOrders} object containing all user orders.
1145
+ */
1146
+ async getOrders(params) {
1147
+ return getOrders(params);
1148
+ }
1149
+ };
1150
+
1151
+ // src/react/SwapProvider.tsx
1152
+ var import_jsx_runtime = require("react/jsx-runtime");
1153
+ var SwapContext = (0, import_react.createContext)(null);
1154
+ var SwapProvider = ({ config, children }) => {
1155
+ const sdk = (0, import_react.useMemo)(() => new SwapSDK(config), [config.apiKey]);
1156
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwapContext.Provider, { value: sdk, children });
1157
+ };
1158
+ var useSwap = () => {
1159
+ const ctx = (0, import_react.useContext)(SwapContext);
1160
+ if (!ctx) {
1161
+ throw new Error("useSwap must be used within <SwapProvider>");
1162
+ }
1163
+ return ctx;
1164
+ };
1165
+
1166
+ // src/react/useQuote.ts
1167
+ var import_react2 = require("react");
1168
+ var import_swr = __toESM(require("swr"), 1);
1169
+ var QUOTE_KEY = "quote-global";
1170
+ function isValidQuoteParams(p) {
1171
+ if (!p) return false;
1172
+ const { tokenIn, tokenOut, amount } = p;
1173
+ if (!tokenIn || !tokenOut || !amount) return false;
1174
+ const n = Number(amount);
1175
+ return Number.isFinite(n) && n > 0;
1176
+ }
1177
+ function useQuote(initialParams) {
1178
+ const sdk = useSwap();
1179
+ const abortRef = (0, import_react2.useRef)(null);
1180
+ const paramsRef = globalThis.__QUOTE_PARAMS_REF__ ?? (globalThis.__QUOTE_PARAMS_REF__ = { current: initialParams ?? null });
774
1181
  (0, import_react2.useEffect)(() => {
775
- return () => {
776
- isMounted.current = false;
777
- };
778
- }, []);
779
- const execute = (0, import_react2.useCallback)(
1182
+ if (initialParams && JSON.stringify(paramsRef.current) !== JSON.stringify(initialParams)) {
1183
+ paramsRef.current = initialParams;
1184
+ void (0, import_swr.mutate)(QUOTE_KEY);
1185
+ }
1186
+ }, [initialParams]);
1187
+ const fetcher = (0, import_react2.useCallback)(async () => {
1188
+ const activeParams = paramsRef.current;
1189
+ if (!isValidQuoteParams(activeParams)) return null;
1190
+ if (abortRef.current) abortRef.current.abort();
1191
+ const controller = new AbortController();
1192
+ abortRef.current = controller;
1193
+ try {
1194
+ return await sdk.getQuote(activeParams);
1195
+ } catch (err) {
1196
+ if (err instanceof DOMException && err.name === "AbortError") return null;
1197
+ if (err instanceof Error) throw err;
1198
+ throw new Error(String(err));
1199
+ }
1200
+ }, [sdk]);
1201
+ const {
1202
+ data,
1203
+ error,
1204
+ isValidating: loading,
1205
+ mutate: mutateQuote
1206
+ } = (0, import_swr.default)(QUOTE_KEY, fetcher, {
1207
+ revalidateOnFocus: false,
1208
+ shouldRetryOnError: false,
1209
+ keepPreviousData: true
1210
+ });
1211
+ const refetch = (0, import_react2.useCallback)(async () => {
1212
+ await mutateQuote();
1213
+ }, [mutateQuote]);
1214
+ const setParams = (0, import_react2.useCallback)(
1215
+ (next) => {
1216
+ paramsRef.current = next;
1217
+ void (0, import_swr.mutate)(QUOTE_KEY);
1218
+ },
1219
+ []
1220
+ );
1221
+ return (0, import_react2.useMemo)(
1222
+ () => ({
1223
+ data,
1224
+ loading,
1225
+ error: error instanceof Error ? error.message : null,
1226
+ refetch,
1227
+ setParams,
1228
+ get activeParams() {
1229
+ return paramsRef.current;
1230
+ }
1231
+ }),
1232
+ [data, loading, error, refetch, setParams]
1233
+ );
1234
+ }
1235
+
1236
+ // src/react/useExecuteTransaction.ts
1237
+ var import_react4 = require("react");
1238
+
1239
+ // src/react/useBalances.ts
1240
+ var import_react3 = require("react");
1241
+ var import_swr2 = __toESM(require("swr"), 1);
1242
+ var BALANCE_KEY = "balances-global";
1243
+ function useBalances(initialParams) {
1244
+ const sdk = useSwap();
1245
+ const abortRef = (0, import_react3.useRef)(null);
1246
+ const paramsRef = globalThis.__BALANCES_PARAMS_REF__ ?? (globalThis.__BALANCES_PARAMS_REF__ = { current: initialParams ?? null });
1247
+ const fetcher = (0, import_react3.useCallback)(async () => {
1248
+ const activeParams = paramsRef.current;
1249
+ if (!activeParams) return null;
1250
+ if (abortRef.current) abortRef.current.abort();
1251
+ const controller = new AbortController();
1252
+ abortRef.current = controller;
1253
+ try {
1254
+ return await sdk.getBalances(activeParams, { signal: controller.signal });
1255
+ } catch (err) {
1256
+ if (err instanceof DOMException && err.name === "AbortError") return null;
1257
+ if (err instanceof Error) throw err;
1258
+ throw new Error(String(err));
1259
+ }
1260
+ }, [sdk, paramsRef]);
1261
+ const {
1262
+ data,
1263
+ error,
1264
+ isValidating: loading,
1265
+ mutate: mutateBalances
1266
+ } = (0, import_swr2.default)(BALANCE_KEY, fetcher, {
1267
+ revalidateOnFocus: false,
1268
+ shouldRetryOnError: false,
1269
+ keepPreviousData: true
1270
+ });
1271
+ const refetch = (0, import_react3.useCallback)(async () => {
1272
+ await mutateBalances();
1273
+ }, [mutateBalances]);
1274
+ const setParams = (0, import_react3.useCallback)((next) => {
1275
+ paramsRef.current = next;
1276
+ void (0, import_swr2.mutate)(BALANCE_KEY);
1277
+ }, [paramsRef]);
1278
+ (0, import_react3.useEffect)(() => {
1279
+ if (initialParams) {
1280
+ const prevParams = paramsRef.current;
1281
+ const paramsChanged = !prevParams || prevParams.addresses.svm !== initialParams.addresses.svm || prevParams.addresses.evm !== initialParams.addresses.evm;
1282
+ if (paramsChanged) {
1283
+ paramsRef.current = initialParams;
1284
+ void (0, import_swr2.mutate)(BALANCE_KEY);
1285
+ }
1286
+ }
1287
+ }, [initialParams, paramsRef]);
1288
+ return (0, import_react3.useMemo)(
1289
+ () => ({
1290
+ data,
1291
+ loading,
1292
+ error: error instanceof Error ? error : null,
1293
+ refetch,
1294
+ setParams,
1295
+ get activeParams() {
1296
+ return paramsRef.current;
1297
+ }
1298
+ }),
1299
+ [data, loading, error, refetch, setParams, paramsRef]
1300
+ );
1301
+ }
1302
+
1303
+ // src/react/useExecuteTransaction.ts
1304
+ function useExecuteTransaction() {
1305
+ const sdk = useSwap();
1306
+ const [isLoading, setLoading] = (0, import_react4.useState)(false);
1307
+ const [stage, setStage] = (0, import_react4.useState)(null);
1308
+ const [message, setMessage] = (0, import_react4.useState)(null);
1309
+ const [error, setError] = (0, import_react4.useState)(null);
1310
+ const [result, setResult] = (0, import_react4.useState)(null);
1311
+ const { refetch: refetchQuote } = useQuote();
1312
+ const { refetch: refetchBalances } = useBalances();
1313
+ const execute = (0, import_react4.useCallback)(
780
1314
  async ({
781
1315
  quote,
782
1316
  accountAddress,
783
1317
  recipientAddress,
784
1318
  wallet,
785
- deadline
1319
+ orderType,
1320
+ options
786
1321
  }) => {
787
- if (!quote || !wallet) {
788
- throw new Error("Quote and wallet are required for order execution.");
789
- }
790
1322
  setLoading(true);
791
1323
  setError(null);
792
- setData(null);
793
- setMessage(null);
1324
+ setResult(null);
1325
+ const onStatus = (s, msg) => {
1326
+ setStage(s);
1327
+ setMessage(msg ?? "");
1328
+ };
794
1329
  try {
795
- const effectiveDeadline = deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
796
- const onStatus = (stage, msg) => {
797
- if (!isMounted.current) return;
798
- setStatus(stage);
799
- if (msg) setMessage(msg);
800
- };
801
- const result = await executeOrder({
1330
+ const res = await sdk.executeTransaction({
802
1331
  quote,
1332
+ wallet,
803
1333
  accountAddress,
804
1334
  recipientAddress,
805
- wallet,
806
1335
  onStatus,
807
- options: { deadline: effectiveDeadline }
1336
+ orderType,
1337
+ options
808
1338
  });
809
- if (!isMounted.current) return result;
810
- setData(result);
811
- setStatus(result.stage);
812
- setMessage("Order executed successfully");
813
- return result;
814
- } catch (err) {
815
- const errorObj = err instanceof Error ? err : new Error(String(err));
816
- if (isMounted.current) {
817
- setError(errorObj);
818
- setStatus("error");
819
- setMessage(errorObj.message);
820
- setData({
821
- status: false,
822
- stage: "error",
823
- message: errorObj.message
1339
+ if (res && typeof res === "object" && "status" in res && "stage" in res && typeof res.stage === "string") {
1340
+ setResult({
1341
+ ...res,
1342
+ stage: res.stage
824
1343
  });
1344
+ } else {
1345
+ setResult(res);
825
1346
  }
826
- return {
827
- status: false,
828
- stage: "error",
829
- message: errorObj.message
830
- };
1347
+ return res;
1348
+ } catch (err) {
1349
+ const msg = err instanceof Error ? err.message : String(err);
1350
+ setError(msg);
1351
+ throw err;
831
1352
  } finally {
832
- if (isMounted.current) setLoading(false);
1353
+ await Promise.allSettled([refetchQuote(), refetchBalances()]);
1354
+ setLoading(false);
833
1355
  }
834
1356
  },
835
- []
1357
+ [sdk, refetchQuote, refetchBalances]
836
1358
  );
837
1359
  return {
838
- /** Executes the swap order. */
839
1360
  execute,
840
- /** Current execution stage. */
841
- status,
842
- /** Human-readable status message. */
1361
+ isLoading,
1362
+ stage,
843
1363
  message,
844
- /** Whether execution is ongoing. */
845
- loading,
846
- /** Raw SDK response data. */
847
- data,
848
- /** Captured error (if execution failed). */
849
- error
1364
+ error,
1365
+ result
850
1366
  };
851
1367
  }
852
1368
 
853
- // src/react/useQuote.ts
854
- var import_react3 = require("react");
855
-
856
- // src/core/getQuote.ts
857
- var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
858
- var import_viem6 = require("viem");
859
- async function getQuote(params) {
860
- if (!params.tokenIn?.address || !params.tokenOut?.address) {
861
- throw new Error("Both tokenIn and tokenOut must include an address.");
862
- }
863
- if (!params.sourceChainId || !params.destChainId) {
864
- throw new Error("Both sourceChainId and destChainId are required.");
865
- }
866
- if (params.amount <= 0n) {
867
- throw new Error("Amount must be greater than 0.");
868
- }
869
- const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
870
- const data = await import_intents_sdk10.QuoteProvider.getQuote({
871
- sourceChainId: params.sourceChainId,
872
- destChainId: params.destChainId,
873
- tokenIn: normalizedTokenIn,
874
- tokenOut: params.tokenOut.address,
875
- amount: params.amount
876
- });
877
- const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
878
- let warning;
879
- if (slippagePercent > 10) {
880
- warning = `\u26A0\uFE0F High slippage tolerance (${slippagePercent.toFixed(2)}%) \u2014 price may vary significantly.`;
881
- }
882
- const estimatedAmountOut = BigInt(data.estimatedAmountOut);
883
- const slippageBps = BigInt(Math.round(slippagePercent * 100));
884
- const estimatedAmountOutAfterSlippage = estimatedAmountOut * (10000n - slippageBps) / 10000n;
885
- const pricePerTokenOutInUsd = data.estimatedAmountOutUsd / Number(data.estimatedAmountOut);
886
- const amountOutUsdAfterSlippage = Number(estimatedAmountOutAfterSlippage) * pricePerTokenOutInUsd;
887
- const minStablecoinsAmountValue = BigInt(data.estimatedAmountInAsMinStablecoinAmount);
888
- const minStablecoinsAmountAfterSlippage = minStablecoinsAmountValue * (10000n - slippageBps) / 10000n;
889
- const pricePerInputToken = estimatedAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / BigInt(params.amount);
890
- return {
891
- amountOut: estimatedAmountOutAfterSlippage,
892
- amountOutUsd: amountOutUsdAfterSlippage,
893
- amountInUsd: data.amountInUsd,
894
- // Input USD stays the same
895
- minStablecoinsAmount: minStablecoinsAmountAfterSlippage,
896
- tokenIn: {
897
- address: params.tokenIn.address,
898
- decimals: params.tokenIn.decimals ?? 18,
899
- chainId: params.sourceChainId
900
- },
901
- tokenOut: {
902
- address: params.tokenOut.address,
903
- decimals: params.tokenOut.decimals ?? 18,
904
- chainId: params.destChainId
905
- },
906
- amountIn: params.amount,
907
- pricePerInputToken,
908
- slippage: slippagePercent,
909
- internal: {
910
- ...data,
911
- estimatedAmountOutReduced: estimatedAmountOutAfterSlippage,
912
- estimatedAmountOutUsdReduced: amountOutUsdAfterSlippage
1369
+ // src/react/useTokenList.ts
1370
+ var import_react5 = require("react");
1371
+ function useTokenList() {
1372
+ const [tokens, setTokens] = (0, import_react5.useState)([]);
1373
+ const [loading, setLoading] = (0, import_react5.useState)(false);
1374
+ const [error, setError] = (0, import_react5.useState)(null);
1375
+ const [hasMore, setHasMore] = (0, import_react5.useState)(true);
1376
+ const [page, setPage] = (0, import_react5.useState)(1);
1377
+ const sdk = useSwap();
1378
+ const pageRef = (0, import_react5.useRef)(1);
1379
+ const hasMoreRef = (0, import_react5.useRef)(true);
1380
+ const lastQuery = (0, import_react5.useRef)({});
1381
+ const cache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
1382
+ const isLoadingRef = (0, import_react5.useRef)(false);
1383
+ pageRef.current = page;
1384
+ hasMoreRef.current = hasMore;
1385
+ const loadTokens = (0, import_react5.useCallback)(
1386
+ async (params) => {
1387
+ const { q, networkId, reset } = params;
1388
+ if (isLoadingRef.current && !reset) return;
1389
+ try {
1390
+ let currentPage = pageRef.current;
1391
+ if (reset) {
1392
+ currentPage = 1;
1393
+ setTokens([]);
1394
+ setPage(1);
1395
+ setHasMore(true);
1396
+ pageRef.current = 1;
1397
+ hasMoreRef.current = true;
1398
+ }
1399
+ if (!reset && !hasMoreRef.current) return;
1400
+ isLoadingRef.current = true;
1401
+ setLoading(true);
1402
+ setError(null);
1403
+ const cacheKey = JSON.stringify({
1404
+ q: q?.toLowerCase() ?? "",
1405
+ networkId: networkId ?? void 0,
1406
+ page: currentPage
1407
+ });
1408
+ if (cache.current.has(cacheKey)) {
1409
+ const cached = cache.current.get(cacheKey);
1410
+ setTokens((prev) => reset ? cached.results : [...prev, ...cached.results]);
1411
+ if (!reset && cached.results.length > 0) {
1412
+ const nextPage = currentPage + 1;
1413
+ setPage(nextPage);
1414
+ pageRef.current = nextPage;
1415
+ }
1416
+ isLoadingRef.current = false;
1417
+ setLoading(false);
1418
+ return;
1419
+ }
1420
+ const apiParams = {
1421
+ q,
1422
+ page: currentPage,
1423
+ limit: 20,
1424
+ ...networkId !== void 0 ? { networkId } : {}
1425
+ };
1426
+ const res = await sdk.getTokenList(apiParams);
1427
+ cache.current.set(cacheKey, res);
1428
+ setTokens((prev) => reset ? res.results : [...prev, ...res.results]);
1429
+ const isLastPage = res.results.length === 0 || res.results.length < 20 || res.count && currentPage * 20 >= res.count;
1430
+ setHasMore(!isLastPage);
1431
+ hasMoreRef.current = !isLastPage;
1432
+ if (!reset && !isLastPage) {
1433
+ const nextPage = currentPage + 1;
1434
+ setPage(nextPage);
1435
+ pageRef.current = nextPage;
1436
+ }
1437
+ lastQuery.current = { q, networkId };
1438
+ } catch (e) {
1439
+ console.error("useTokenList error:", e);
1440
+ setError("Failed to load tokens");
1441
+ } finally {
1442
+ setLoading(false);
1443
+ isLoadingRef.current = false;
1444
+ }
913
1445
  },
914
- warning
1446
+ [sdk]
1447
+ );
1448
+ const resetTokens = (0, import_react5.useCallback)(() => {
1449
+ setTokens([]);
1450
+ setPage(1);
1451
+ setHasMore(true);
1452
+ pageRef.current = 1;
1453
+ hasMoreRef.current = true;
1454
+ cache.current.clear();
1455
+ lastQuery.current = {};
1456
+ }, []);
1457
+ return {
1458
+ tokens,
1459
+ loading,
1460
+ error,
1461
+ hasMore,
1462
+ page,
1463
+ lastQuery: lastQuery.current,
1464
+ loadTokens,
1465
+ resetTokens
915
1466
  };
916
1467
  }
917
1468
 
918
- // src/react/useQuote.ts
919
- function useQuote(params, options) {
920
- const [data, setData] = (0, import_react3.useState)(null);
921
- const [loading, setLoading] = (0, import_react3.useState)(false);
922
- const [error, setError] = (0, import_react3.useState)(null);
923
- const [warning, setWarning] = (0, import_react3.useState)(null);
924
- const debounceMs = options?.debounceMs ?? 250;
925
- const autoRefreshMs = options?.autoRefreshMs;
926
- const abortRef = (0, import_react3.useRef)(null);
927
- const debounceRef = (0, import_react3.useRef)(null);
928
- const mounted = (0, import_react3.useRef)(false);
929
- const paramsKey = (0, import_react3.useMemo)(
930
- () => params ? JSON.stringify(serializeBigIntsToStrings(params)) : null,
931
- [params]
932
- );
933
- (0, import_react3.useEffect)(() => {
934
- mounted.current = true;
935
- return () => {
936
- mounted.current = false;
937
- abortRef.current?.abort();
938
- if (debounceRef.current) clearTimeout(debounceRef.current);
939
- };
940
- }, []);
941
- const fetchQuote = (0, import_react3.useCallback)(async () => {
942
- if (!params) return;
943
- try {
944
- setLoading(true);
945
- setWarning(null);
946
- const result = await getQuote(params);
947
- const serializeResult = serializeBigIntsToStrings(result);
948
- if (!mounted.current) return;
949
- setData((prev) => {
950
- if (JSON.stringify(prev) === JSON.stringify(serializeResult)) return prev;
951
- return serializeResult;
952
- });
953
- setWarning(result.warning ?? null);
954
- setError(null);
955
- } catch (err) {
956
- if (err.name === "AbortError") return;
957
- console.error("[useQuote] fetch error:", err);
958
- if (mounted.current) setError(err instanceof Error ? err : new Error(String(err)));
959
- } finally {
960
- if (mounted.current) setLoading(false);
961
- }
962
- }, [paramsKey]);
963
- (0, import_react3.useEffect)(() => {
964
- if (!paramsKey) return;
965
- if (debounceRef.current) clearTimeout(debounceRef.current);
966
- debounceRef.current = setTimeout(() => {
967
- fetchQuote();
968
- }, debounceMs);
1469
+ // src/react/useTokensData.ts
1470
+ var import_react6 = require("react");
1471
+ function useTokensData(addresses) {
1472
+ const sdk = useSwap();
1473
+ const [data, setData] = (0, import_react6.useState)([]);
1474
+ const [loading, setLoading] = (0, import_react6.useState)(false);
1475
+ const [error, setError] = (0, import_react6.useState)(null);
1476
+ (0, import_react6.useEffect)(() => {
1477
+ if (!addresses?.length) return;
1478
+ let isMounted = true;
1479
+ setLoading(true);
1480
+ setError(null);
1481
+ sdk.getTokensData(addresses).then((res) => {
1482
+ if (isMounted) setData(res);
1483
+ }).catch((e) => {
1484
+ if (isMounted) setError(e instanceof Error ? e : new Error(String(e)));
1485
+ }).finally(() => {
1486
+ if (isMounted) setLoading(false);
1487
+ });
969
1488
  return () => {
970
- if (debounceRef.current) clearTimeout(debounceRef.current);
971
- abortRef.current?.abort();
1489
+ isMounted = false;
972
1490
  };
973
- }, [paramsKey, debounceMs, fetchQuote]);
974
- (0, import_react3.useEffect)(() => {
975
- if (!autoRefreshMs || !paramsKey) return;
976
- const interval = setInterval(() => fetchQuote(), autoRefreshMs);
977
- return () => clearInterval(interval);
978
- }, [autoRefreshMs, paramsKey, fetchQuote]);
979
- return (0, import_react3.useMemo)(
980
- () => ({
981
- data,
982
- loading,
983
- error,
984
- warning,
985
- refetch: fetchQuote
986
- }),
987
- [data, loading, error, warning, fetchQuote]
988
- );
1491
+ }, [sdk, JSON.stringify(addresses)]);
1492
+ return { data, loading, error };
989
1493
  }
990
1494
 
991
- // src/react/useBalances.ts
992
- var import_react4 = require("react");
993
-
994
- // src/core/getBalances.ts
995
- var import_intents_sdk11 = require("@shogun-sdk/intents-sdk");
996
- async function getBalances(params, options) {
997
- const { addresses, cursorEvm, cursorSvm } = params;
998
- const { signal } = options ?? {};
999
- if (!addresses?.evm && !addresses?.svm) {
1000
- throw new Error("At least one address (EVM or SVM) must be provided.");
1001
- }
1002
- const payload = JSON.stringify({
1003
- addresses,
1004
- cursorEvm,
1005
- cursorSvm
1006
- });
1007
- const start = performance.now();
1008
- const response = await fetch(`${import_intents_sdk11.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
1009
- method: "POST",
1010
- headers: {
1011
- accept: "application/json",
1012
- "Content-Type": "application/json"
1013
- },
1014
- body: payload,
1015
- signal
1016
- }).catch((err) => {
1017
- if (err.name === "AbortError") {
1018
- throw new Error("Balance request was cancelled.");
1019
- }
1020
- throw err;
1021
- });
1022
- if (!response.ok) {
1023
- const text = await response.text().catch(() => "");
1024
- throw new Error(`Failed to fetch balances: ${response.status} ${text}`);
1025
- }
1026
- const data = await response.json().catch(() => {
1027
- throw new Error("Invalid JSON response from balances API.");
1028
- });
1029
- const duration = (performance.now() - start).toFixed(1);
1030
- if (process.env.NODE_ENV !== "production") {
1031
- console.debug(`[Shogun SDK] Fetched balances in ${duration}ms`);
1032
- }
1033
- const evmItems = data.evm?.items ?? [];
1034
- const svmItems = data.svm?.items ?? [];
1035
- const combined = [...evmItems, ...svmItems];
1036
- return {
1037
- results: combined,
1038
- nextCursorEvm: data.evm?.cursor ?? null,
1039
- nextCursorSvm: data.svm?.cursor ?? null
1040
- };
1495
+ // src/react/useOrders.ts
1496
+ var import_react7 = require("react");
1497
+ var import_swr3 = __toESM(require("swr"), 1);
1498
+ var ORDERS_KEY = "orders-global";
1499
+ function hasValidAddress(addrs) {
1500
+ if (!addrs) return false;
1501
+ return Boolean(addrs.evmAddress || addrs.solAddress || addrs.suiAddress);
1041
1502
  }
1042
-
1043
- // src/react/useBalances.ts
1044
- function useBalances(params) {
1045
- const [data, setData] = (0, import_react4.useState)(null);
1046
- const [loading, setLoading] = (0, import_react4.useState)(false);
1047
- const [error, setError] = (0, import_react4.useState)(null);
1048
- const abortRef = (0, import_react4.useRef)(null);
1049
- const stableParams = (0, import_react4.useMemo)(() => {
1050
- if (!params) return null;
1051
- const { addresses, cursorEvm, cursorSvm } = params;
1052
- return {
1053
- addresses: {
1054
- evm: addresses?.evm ?? void 0,
1055
- svm: addresses?.svm ?? void 0
1056
- },
1057
- cursorEvm,
1058
- cursorSvm
1059
- };
1060
- }, [params?.addresses?.evm, params?.addresses?.svm, params?.cursorEvm, params?.cursorSvm]);
1061
- const fetchBalances = (0, import_react4.useCallback)(async () => {
1062
- if (!stableParams) return;
1503
+ function useOrders(initialAddresses) {
1504
+ const sdk = useSwap();
1505
+ const abortRef = (0, import_react7.useRef)(null);
1506
+ const addrRef = globalThis.__ORDERS_ADDR_REF__ ?? (globalThis.__ORDERS_ADDR_REF__ = { current: initialAddresses ?? null });
1507
+ (0, import_react7.useEffect)(() => {
1508
+ if (initialAddresses && JSON.stringify(addrRef.current) !== JSON.stringify(initialAddresses)) {
1509
+ addrRef.current = initialAddresses;
1510
+ void (0, import_swr3.mutate)(ORDERS_KEY);
1511
+ }
1512
+ }, [initialAddresses]);
1513
+ const fetcher = (0, import_react7.useCallback)(async () => {
1514
+ const active = addrRef.current;
1515
+ if (!hasValidAddress(active)) return null;
1063
1516
  if (abortRef.current) abortRef.current.abort();
1064
1517
  const controller = new AbortController();
1065
1518
  abortRef.current = controller;
1066
- setLoading(true);
1067
- setError(null);
1068
1519
  try {
1069
- const result = await getBalances(stableParams, { signal: controller.signal });
1070
- setData((prev) => {
1071
- if (JSON.stringify(prev) === JSON.stringify(result)) return prev;
1072
- return result;
1073
- });
1074
- return result;
1520
+ return await sdk.getOrders(active ?? {});
1075
1521
  } catch (err) {
1076
- if (err.name === "AbortError") return;
1077
- const e = err instanceof Error ? err : new Error(String(err));
1078
- setError(e);
1079
- throw e;
1080
- } finally {
1081
- setLoading(false);
1522
+ if (err instanceof DOMException && err.name === "AbortError") return null;
1523
+ if (err instanceof Error) throw err;
1524
+ throw new Error(String(err));
1082
1525
  }
1083
- }, [stableParams]);
1084
- (0, import_react4.useEffect)(() => {
1085
- if (stableParams) fetchBalances().catch(() => {
1086
- });
1087
- return () => {
1088
- if (abortRef.current) abortRef.current.abort();
1089
- };
1090
- }, [fetchBalances]);
1091
- return (0, import_react4.useMemo)(
1526
+ }, [sdk]);
1527
+ const {
1528
+ data,
1529
+ error,
1530
+ isValidating: loading,
1531
+ mutate: mutateOrders
1532
+ } = (0, import_swr3.default)(ORDERS_KEY, fetcher, {
1533
+ revalidateOnFocus: false,
1534
+ revalidateOnReconnect: false,
1535
+ shouldRetryOnError: false,
1536
+ keepPreviousData: true
1537
+ });
1538
+ const refetch = (0, import_react7.useCallback)(async () => {
1539
+ await mutateOrders();
1540
+ }, [mutateOrders]);
1541
+ const setAddresses = (0, import_react7.useCallback)(
1542
+ (next) => {
1543
+ if (!next) return;
1544
+ addrRef.current = next;
1545
+ void (0, import_swr3.mutate)(ORDERS_KEY);
1546
+ },
1547
+ []
1548
+ );
1549
+ return (0, import_react7.useMemo)(
1092
1550
  () => ({
1093
- /** Latest fetched balance data */
1094
1551
  data,
1095
- /** Whether the hook is currently fetching */
1096
1552
  loading,
1097
- /** Error object if fetching failed */
1098
- error,
1099
- /** Manually trigger a refresh */
1100
- refetch: fetchBalances
1553
+ error: error instanceof Error ? error.message : null,
1554
+ refetch,
1555
+ setAddresses,
1556
+ get activeAddresses() {
1557
+ return addrRef.current;
1558
+ }
1101
1559
  }),
1102
- [data, loading, error, fetchBalances]
1560
+ [data, loading, error, refetch, setAddresses]
1103
1561
  );
1104
1562
  }
1105
-
1106
- // src/react/index.ts
1107
- var import_intents_sdk12 = require("@shogun-sdk/intents-sdk");