@shogun-sdk/swap 0.0.2-test.4 → 0.0.2-test.41

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,107 +18,49 @@ 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_sdk10.ChainID,
24
- isEvmChain: () => import_intents_sdk10.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
+ useCancelOrder: () => useCancelOrder,
43
+ useExecuteTransaction: () => useExecuteTransaction,
44
+ useOrders: () => useOrders,
27
45
  useQuote: () => useQuote,
28
- useTokenList: () => useTokenList
46
+ useSwap: () => useSwap,
47
+ useTokenList: () => useTokenList,
48
+ useTokensData: () => useTokensData
29
49
  });
30
50
  module.exports = __toCommonJS(react_exports);
31
51
 
32
- // src/react/useTokenList.ts
52
+ // src/react/SwapProvider.tsx
33
53
  var import_react = require("react");
34
54
 
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");
55
+ // src/core/getQuote.ts
56
+ var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
57
+ var import_viem2 = require("viem");
113
58
 
114
- // src/core/executeOrder/execute.ts
115
- var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
116
- var import_viem3 = require("viem");
59
+ // src/core/execute/normalizeNative.ts
60
+ var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
117
61
 
118
62
  // src/utils/address.ts
63
+ var import_viem = require("viem");
119
64
  var NATIVE_TOKEN = {
120
65
  ETH: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
121
66
  SOL: "So11111111111111111111111111111111111111111",
@@ -126,13 +71,32 @@ var isNativeAddress = (tokenAddress) => {
126
71
  const normalizedTokenAddress = tokenAddress.toLowerCase();
127
72
  return !!tokenAddress && NATIVE_ADDRESSES.includes(normalizedTokenAddress);
128
73
  };
74
+ function normalizeEvmTokenAddress(address) {
75
+ const lower = address.toLowerCase();
76
+ return lower === NATIVE_TOKEN.ETH.toLowerCase() ? import_viem.zeroAddress : address;
77
+ }
129
78
 
130
79
  // src/utils/chain.ts
131
- var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
132
- var SOLANA_CHAIN_ID = import_intents_sdk2.ChainID.Solana;
133
- var SupportedChains = [
80
+ var import_intents_sdk = require("@shogun-sdk/intents-sdk");
81
+ var SOLANA_CHAIN_ID = import_intents_sdk.ChainID.Solana;
82
+ var CURRENT_SUPPORTED = [
83
+ import_intents_sdk.ChainID.Solana,
84
+ import_intents_sdk.ChainID.BSC,
85
+ import_intents_sdk.ChainID.Base,
86
+ import_intents_sdk.ChainID.MONAD
87
+ ];
88
+ var ChainId = Object.entries(import_intents_sdk.ChainID).reduce(
89
+ (acc, [key, value]) => {
90
+ if (typeof value === "number" && CURRENT_SUPPORTED.includes(value)) {
91
+ acc[key] = value;
92
+ }
93
+ return acc;
94
+ },
95
+ {}
96
+ );
97
+ var SupportedChainsInternal = [
134
98
  {
135
- id: import_intents_sdk2.ChainID.Arbitrum,
99
+ id: import_intents_sdk.ChainID.Arbitrum,
136
100
  name: "Arbitrum",
137
101
  isEVM: true,
138
102
  wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -141,7 +105,7 @@ var SupportedChains = [
141
105
  tokenAddress: NATIVE_TOKEN.ETH
142
106
  },
143
107
  {
144
- id: import_intents_sdk2.ChainID.Optimism,
108
+ id: import_intents_sdk.ChainID.Optimism,
145
109
  name: "Optimism",
146
110
  isEVM: true,
147
111
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -150,7 +114,7 @@ var SupportedChains = [
150
114
  tokenAddress: NATIVE_TOKEN.ETH
151
115
  },
152
116
  {
153
- id: import_intents_sdk2.ChainID.Base,
117
+ id: import_intents_sdk.ChainID.Base,
154
118
  name: "Base",
155
119
  isEVM: true,
156
120
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -159,7 +123,7 @@ var SupportedChains = [
159
123
  tokenAddress: NATIVE_TOKEN.ETH
160
124
  },
161
125
  {
162
- id: import_intents_sdk2.ChainID.Hyperliquid,
126
+ id: import_intents_sdk.ChainID.Hyperliquid,
163
127
  name: "Hyperliquid",
164
128
  isEVM: true,
165
129
  wrapped: "0x5555555555555555555555555555555555555555",
@@ -168,7 +132,7 @@ var SupportedChains = [
168
132
  tokenAddress: NATIVE_TOKEN.ETH
169
133
  },
170
134
  {
171
- id: import_intents_sdk2.ChainID.BSC,
135
+ id: import_intents_sdk.ChainID.BSC,
172
136
  name: "BSC",
173
137
  isEVM: true,
174
138
  wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
@@ -184,8 +148,21 @@ var SupportedChains = [
184
148
  symbol: "SOL",
185
149
  decimals: 9,
186
150
  tokenAddress: NATIVE_TOKEN.SOL
151
+ },
152
+ {
153
+ id: import_intents_sdk.ChainID.MONAD,
154
+ name: "Monad",
155
+ isEVM: true,
156
+ wrapped: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
157
+ symbol: "MON",
158
+ decimals: 18,
159
+ tokenAddress: NATIVE_TOKEN.ETH
187
160
  }
188
161
  ];
162
+ var SupportedChains = SupportedChainsInternal.filter(
163
+ (c) => CURRENT_SUPPORTED.includes(c.id)
164
+ );
165
+ var isEvmChain = import_intents_sdk.isEvmChain;
189
166
 
190
167
  // src/utils/viem.ts
191
168
  function isViemWalletClient(wallet) {
@@ -213,10 +190,227 @@ function serializeBigIntsToStrings(obj) {
213
190
  return obj;
214
191
  }
215
192
 
193
+ // src/core/execute/normalizeNative.ts
194
+ function normalizeNative(chainId, address) {
195
+ if ((0, import_intents_sdk2.isEvmChain)(chainId) && isNativeAddress(address)) {
196
+ const chain = SupportedChains.find((c) => c.id === chainId);
197
+ if (!chain?.wrapped)
198
+ throw new Error(`Wrapped token not found for chainId ${chainId}`);
199
+ return chain.wrapped;
200
+ }
201
+ return address;
202
+ }
203
+
204
+ // src/core/getQuote.ts
205
+ async function getQuote(params) {
206
+ const amount = BigInt(params.amount);
207
+ if (!params.tokenIn?.address || !params.tokenOut?.address) {
208
+ throw new Error("Both tokenIn and tokenOut must include an address.");
209
+ }
210
+ if (!params.sourceChainId || !params.destChainId) {
211
+ throw new Error("Both sourceChainId and destChainId are required.");
212
+ }
213
+ if (amount <= 0n) {
214
+ throw new Error("Amount must be greater than 0.");
215
+ }
216
+ const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
217
+ const slippageBps = BigInt(Math.round(slippagePercent * 100));
218
+ const applyUserSlippage = (value) => value * (10000n - slippageBps) / 10000n;
219
+ let warning;
220
+ if (slippagePercent > 10) {
221
+ warning = `\u26A0\uFE0F High slippage tolerance (${slippagePercent.toFixed(2)}%) \u2014 price may vary significantly.`;
222
+ }
223
+ const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
224
+ const isSingleChain = params.sourceChainId === params.destChainId;
225
+ let data;
226
+ let netFloor;
227
+ let minStablecoinsAmount;
228
+ if (isSingleChain) {
229
+ const { quote, netAmountOut } = await import_intents_sdk3.QuoteProvider.getSingleChainNetQuote({
230
+ chainId: params.sourceChainId,
231
+ amount,
232
+ tokenIn: normalizedTokenIn,
233
+ tokenOut: params.tokenOut.address
234
+ });
235
+ netFloor = netAmountOut;
236
+ minStablecoinsAmount = 0n;
237
+ data = {
238
+ amountInUsd: quote.amountInUsd,
239
+ estimatedAmountInAsMinStablecoinAmount: 0n,
240
+ estimatedAmountOut: quote.amountOut,
241
+ estimatedAmountOutUsd: quote.amountOutUsd,
242
+ // filled in below once the user slippage buffer is known
243
+ estimatedAmountOutReduced: netAmountOut,
244
+ estimatedAmountOutUsdReduced: quote.amountOutUsd,
245
+ tokenIn: { address: params.tokenIn.address, chainId: params.sourceChainId },
246
+ tokenOut: { address: params.tokenOut.address, chainId: params.destChainId }
247
+ };
248
+ } else {
249
+ const crossChainQuote = await import_intents_sdk3.QuoteProvider.getCrossChainNetQuote({
250
+ sourceChainId: params.sourceChainId,
251
+ destChainId: params.destChainId,
252
+ tokenIn: normalizedTokenIn,
253
+ tokenOut: params.tokenOut.address,
254
+ amount
255
+ });
256
+ data = crossChainQuote;
257
+ netFloor = BigInt(crossChainQuote.estimatedAmountOutReduced);
258
+ minStablecoinsAmount = applyUserSlippage(
259
+ BigInt(crossChainQuote.estimatedAmountInAsMinStablecoinAmount)
260
+ );
261
+ }
262
+ const amountOut = applyUserSlippage(netFloor);
263
+ const grossAmountOut = BigInt(data.estimatedAmountOut);
264
+ const pricePerTokenOutInUsd = grossAmountOut > 0n ? data.estimatedAmountOutUsd / Number(grossAmountOut) : 0;
265
+ const amountOutUsd = Number(amountOut) * pricePerTokenOutInUsd;
266
+ const pricePerInputToken = grossAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / amount;
267
+ return {
268
+ amountOut,
269
+ amountOutUsd,
270
+ amountInUsd: data.amountInUsd,
271
+ minStablecoinsAmount,
272
+ tokenIn: {
273
+ address: params.tokenIn.address,
274
+ decimals: params.tokenIn.decimals ?? 18,
275
+ chainId: params.sourceChainId
276
+ },
277
+ tokenOut: {
278
+ address: params.tokenOut.address,
279
+ decimals: params.tokenOut.decimals ?? 18,
280
+ chainId: params.destChainId
281
+ },
282
+ amountIn: amount,
283
+ pricePerInputToken,
284
+ slippage: slippagePercent,
285
+ internal: {
286
+ ...data,
287
+ estimatedAmountOutReduced: amountOut,
288
+ estimatedAmountOutUsdReduced: amountOutUsd
289
+ },
290
+ warning
291
+ };
292
+ }
293
+ function buildQuoteParams({
294
+ tokenIn,
295
+ tokenOut,
296
+ sourceChainId,
297
+ destChainId,
298
+ amount,
299
+ slippage
300
+ }) {
301
+ return {
302
+ tokenIn,
303
+ tokenOut,
304
+ sourceChainId,
305
+ destChainId,
306
+ amount: (0, import_viem2.parseUnits)(amount.toString(), tokenIn.decimals ?? 18).toString(),
307
+ slippage
308
+ };
309
+ }
310
+
311
+ // src/core/getBalances.ts
312
+ var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
313
+ async function getBalances(params, options) {
314
+ const { addresses, cursorEvm, cursorSvm } = params;
315
+ const { signal } = options ?? {};
316
+ if (!addresses?.evm && !addresses?.svm) {
317
+ throw new Error("At least one address (EVM or SVM) must be provided.");
318
+ }
319
+ const payload = JSON.stringify({
320
+ addresses,
321
+ cursorEvm,
322
+ cursorSvm
323
+ });
324
+ const start = performance.now();
325
+ const response = await fetch(`${import_intents_sdk4.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
326
+ method: "POST",
327
+ headers: {
328
+ accept: "application/json",
329
+ "Content-Type": "application/json"
330
+ },
331
+ body: payload,
332
+ signal
333
+ }).catch((err) => {
334
+ if (err.name === "AbortError") {
335
+ throw new Error("Balance request was cancelled.");
336
+ }
337
+ throw err;
338
+ });
339
+ if (!response.ok) {
340
+ const text = await response.text().catch(() => "");
341
+ throw new Error(`Failed to fetch balances: ${response.status} ${text}`);
342
+ }
343
+ const data = await response.json().catch(() => {
344
+ throw new Error("Invalid JSON response from balances API.");
345
+ });
346
+ const duration = (performance.now() - start).toFixed(1);
347
+ if (process.env.NODE_ENV !== "production") {
348
+ console.debug(`[Shogun SDK] Fetched balances in ${duration}ms`);
349
+ }
350
+ const evmItems = data.evm?.items ?? [];
351
+ const svmItems = data.svm?.items ?? [];
352
+ const combined = [...evmItems, ...svmItems];
353
+ const filtered = combined.filter(
354
+ (b) => CURRENT_SUPPORTED.includes(b.chainId)
355
+ );
356
+ return {
357
+ results: filtered,
358
+ nextCursorEvm: data.evm?.cursor ?? null,
359
+ nextCursorSvm: data.svm?.cursor ?? null
360
+ };
361
+ }
362
+
363
+ // src/core/token-list.ts
364
+ var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
365
+ async function getTokenList(params) {
366
+ const url = new URL(`${import_intents_sdk5.TOKEN_SEARCH_API_BASE_URL}/tokens/search`);
367
+ if (params.q) url.searchParams.append("q", params.q);
368
+ if (params.networkId) url.searchParams.append("networkId", String(params.networkId));
369
+ if (params.page) url.searchParams.append("page", String(params.page));
370
+ if (params.limit) url.searchParams.append("limit", String(params.limit));
371
+ const res = await fetch(url.toString(), {
372
+ signal: params.signal
373
+ });
374
+ if (!res.ok) {
375
+ throw new Error(`Failed to fetch tokens: ${res.status} ${res.statusText}`);
376
+ }
377
+ const data = await res.json();
378
+ const filteredResults = data.results.filter(
379
+ (token) => CURRENT_SUPPORTED.includes(token.chainId)
380
+ );
381
+ return {
382
+ ...data,
383
+ results: filteredResults,
384
+ count: filteredResults.length
385
+ };
386
+ }
387
+
388
+ // src/core/token.ts
389
+ var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
390
+ async function getTokensData(addresses) {
391
+ if (!addresses?.length) return [];
392
+ const response = await fetch(`${import_intents_sdk6.TOKEN_SEARCH_API_BASE_URL}/tokens/tokens`, {
393
+ method: "POST",
394
+ headers: {
395
+ "Content-Type": "application/json",
396
+ accept: "*/*"
397
+ },
398
+ body: JSON.stringify({ addresses })
399
+ });
400
+ if (!response.ok) {
401
+ throw new Error(`Failed to fetch token data: ${response.statusText}`);
402
+ }
403
+ const data = await response.json();
404
+ const filtered = data.filter((t) => CURRENT_SUPPORTED.includes(Number(t.chainId)));
405
+ return filtered;
406
+ }
407
+
408
+ // src/core/execute/execute.ts
409
+ var import_intents_sdk12 = require("@shogun-sdk/intents-sdk");
410
+ var import_viem7 = require("viem");
411
+
216
412
  // src/wallet-adapter/evm-wallet-adapter/adapter.ts
217
- var import_ethers = require("ethers/lib/ethers.js");
218
- var import_utils = require("ethers/lib/utils.js");
219
- var import_viem = require("viem");
413
+ var import_viem3 = require("viem");
220
414
  function isEVMTransaction(tx) {
221
415
  return typeof tx.from === "string";
222
416
  }
@@ -234,15 +428,26 @@ var adaptViemWallet = (wallet) => {
234
428
  if (!isEVMTransaction(transaction)) {
235
429
  throw new Error("Expected EVMTransaction but got SolanaTransaction");
236
430
  }
237
- const tx = await wallet.sendTransaction({
238
- from: transaction.from,
239
- to: transaction.to,
240
- data: transaction.data,
241
- value: transaction.value,
242
- account: wallet.account?.address,
243
- chain: wallet.chain
244
- });
245
- return tx;
431
+ if (wallet.transport.type === "http") {
432
+ const request = await wallet.prepareTransactionRequest({
433
+ to: transaction.to,
434
+ data: transaction.data,
435
+ value: transaction.value,
436
+ chain: wallet.chain
437
+ });
438
+ const serializedTransaction = await wallet.signTransaction(request);
439
+ const tx = await wallet.sendRawTransaction({ serializedTransaction });
440
+ return tx;
441
+ } else {
442
+ const hash = await wallet.sendTransaction({
443
+ to: transaction.to,
444
+ data: transaction.data,
445
+ value: transaction.value,
446
+ chain: wallet.chain,
447
+ account: wallet.account
448
+ });
449
+ return hash;
450
+ }
246
451
  };
247
452
  const switchChain = async (chainId) => {
248
453
  try {
@@ -265,67 +470,96 @@ var adaptViemWallet = (wallet) => {
265
470
  if (!addr) throw new Error("No address found");
266
471
  return addr;
267
472
  };
473
+ const readContract = async ({
474
+ address: address2,
475
+ abi,
476
+ functionName,
477
+ args = []
478
+ }) => {
479
+ const publicClient = wallet.extend(import_viem3.publicActions);
480
+ return await publicClient.readContract({
481
+ address: address2,
482
+ abi,
483
+ functionName,
484
+ args
485
+ });
486
+ };
268
487
  return {
269
488
  vmType: "EVM" /* EVM */,
270
- transport: (0, import_viem.custom)(wallet.transport),
489
+ transport: (0, import_viem3.custom)(wallet.transport),
271
490
  getChainId: async () => wallet.getChainId(),
272
491
  address,
273
492
  sendTransaction,
274
493
  signTypedData,
275
- switchChain
494
+ switchChain,
495
+ readContract
276
496
  };
277
497
  };
278
498
 
279
- // src/core/executeOrder/handleEvmExecution.ts
280
- var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
281
- var import_viem2 = require("viem");
282
-
283
- // src/core/executeOrder/normalizeNative.ts
284
- var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
285
- function normalizeNative(chainId, address) {
286
- if ((0, import_intents_sdk3.isEvmChain)(chainId) && isNativeAddress(address)) {
287
- const chain = SupportedChains.find((c) => c.id === chainId);
288
- if (!chain?.wrapped)
289
- throw new Error(`Wrapped token not found for chainId ${chainId}`);
290
- return chain.wrapped;
291
- }
292
- return address;
293
- }
499
+ // src/core/execute/handleEvmExecution.ts
500
+ var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
501
+ var import_viem6 = require("viem");
294
502
 
295
- // src/core/executeOrder/stageMessages.ts
503
+ // src/core/execute/stageMessages.ts
296
504
  var DEFAULT_STAGE_MESSAGES = {
297
505
  processing: "Preparing transaction for execution",
298
506
  approving: "Approving token allowance",
299
507
  approved: "Token approved successfully",
300
- signing: "Signing order for submission",
301
- submitting: "Submitting order to Auctioneer",
302
- success: "Order executed successfully",
303
- error: "Order execution failed"
508
+ signing: "Signing transaction for submission",
509
+ submitting: "Submitting transaction",
510
+ initiated: "Transaction initiated.",
511
+ success: "Transaction Executed successfully",
512
+ success_limit: "Limit order has been submitted successfully.",
513
+ shogun_processing: "Shogun is processing your transaction",
514
+ error: "Transaction failed during submission"
304
515
  };
305
516
 
306
- // src/core/executeOrder/buildOrder.ts
307
- var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
517
+ // src/core/execute/buildOrder.ts
518
+ var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
519
+ var import_viem4 = require("viem");
520
+
521
+ // src/utils/order.ts
522
+ var OrderExecutionType = /* @__PURE__ */ ((OrderExecutionType2) => {
523
+ OrderExecutionType2["LIMIT"] = "limit";
524
+ OrderExecutionType2["MARKET"] = "market";
525
+ return OrderExecutionType2;
526
+ })(OrderExecutionType || {});
527
+
528
+ // src/core/execute/buildOrder.ts
308
529
  async function buildOrder({
309
530
  quote,
310
531
  accountAddress,
311
532
  destination,
312
533
  deadline,
313
- isSingleChain
534
+ isSingleChain,
535
+ orderType,
536
+ options
314
537
  }) {
315
538
  const { tokenIn, tokenOut } = quote;
539
+ let amountOutMin = BigInt(quote.internal.estimatedAmountOutReduced);
540
+ if (orderType === "limit" /* LIMIT */ && options && "executionPrice" in options) {
541
+ const executionPrice = Number(options.executionPrice);
542
+ if (Number.isFinite(executionPrice) && executionPrice > 0) {
543
+ const decimalsIn = tokenIn.decimals ?? 18;
544
+ const decimalsOut = tokenOut.decimals ?? 18;
545
+ const formattedAmountIn = Number((0, import_viem4.formatUnits)(BigInt(quote.amountIn.toString()), decimalsIn));
546
+ const rawAmountOut = formattedAmountIn * executionPrice;
547
+ amountOutMin = (0, import_viem4.parseUnits)(rawAmountOut.toString(), decimalsOut);
548
+ }
549
+ }
316
550
  if (isSingleChain) {
317
- return await import_intents_sdk4.SingleChainOrder.create({
551
+ return await import_intents_sdk7.SingleChainOrder.create({
318
552
  user: accountAddress,
319
553
  chainId: tokenIn.chainId,
320
554
  tokenIn: tokenIn.address,
321
555
  tokenOut: tokenOut.address,
322
556
  amountIn: quote.amountIn,
323
- amountOutMin: quote.internal.estimatedAmountOutReduced,
557
+ amountOutMin,
324
558
  deadline,
325
559
  destinationAddress: destination
326
560
  });
327
561
  }
328
- return await import_intents_sdk4.CrossChainOrder.create({
562
+ return await import_intents_sdk7.CrossChainOrder.create({
329
563
  user: accountAddress,
330
564
  sourceChainId: tokenIn.chainId,
331
565
  sourceTokenAddress: tokenIn.address,
@@ -334,12 +568,166 @@ async function buildOrder({
334
568
  destinationTokenAddress: tokenOut.address,
335
569
  destinationAddress: destination,
336
570
  deadline,
337
- destinationTokenMinAmount: quote.internal.estimatedAmountOutReduced,
571
+ destinationTokenMinAmount: amountOutMin,
338
572
  minStablecoinAmount: quote.minStablecoinsAmount
339
573
  });
340
574
  }
341
575
 
342
- // src/core/executeOrder/handleEvmExecution.ts
576
+ // src/utils/pollOrderStatus.ts
577
+ var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
578
+ async function pollOrderStatus(address, orderId, options = {}) {
579
+ const { intervalMs = 2e3, timeoutMs = 3e5, authToken } = options;
580
+ const startTime = Date.now();
581
+ const isDebug = process.env.NODE_ENV !== "production";
582
+ const isEvmAddress = /^0x[a-fA-F0-9]{40}$/.test(address);
583
+ const isSuiAddress = /^0x[a-fA-F0-9]{64}$/.test(address);
584
+ const isSolanaAddress = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
585
+ let queryParam;
586
+ if (isEvmAddress) queryParam = `evmWallets=${address}`;
587
+ else if (isSuiAddress) queryParam = `suiWallets=${address}`;
588
+ else if (isSolanaAddress) queryParam = `solanaWallets=${address}`;
589
+ else throw new Error(`Unrecognized wallet address format: ${address}`);
590
+ const queryUrl = `${import_intents_sdk8.AUCTIONEER_URL}/user_intent?${queryParam}`;
591
+ return new Promise((resolve, reject) => {
592
+ const pollInterval = setInterval(async () => {
593
+ try {
594
+ if (Date.now() - startTime > timeoutMs) {
595
+ clearInterval(pollInterval);
596
+ return resolve("Timeout");
597
+ }
598
+ const res = await fetch(queryUrl, {
599
+ method: "GET",
600
+ headers: {
601
+ "Content-Type": "application/json",
602
+ // The /user_intent status endpoint requires the SIWE JWT; without it
603
+ // the request 401s after the order has already been submitted.
604
+ ...authToken ? { Authorization: `Bearer ${authToken}` } : {}
605
+ }
606
+ });
607
+ if (!res.ok) {
608
+ clearInterval(pollInterval);
609
+ return reject(
610
+ new Error(`Failed to fetch orders: ${res.status} ${res.statusText}`)
611
+ );
612
+ }
613
+ const json = await res.json();
614
+ const data = json?.data ?? {};
615
+ const allOrders = [
616
+ ...data.crossChainDcaOrders ?? [],
617
+ ...data.crossChainLimitOrders ?? [],
618
+ ...data.singleChainDcaOrders ?? [],
619
+ ...data.singleChainLimitOrders ?? []
620
+ ];
621
+ const targetOrder = allOrders.find((o) => o.orderId === orderId);
622
+ if (!targetOrder) {
623
+ if (isDebug)
624
+ console.debug(`[pollOrderStatus] [${orderId}] Not found yet`);
625
+ return;
626
+ }
627
+ const { orderStatus } = targetOrder;
628
+ if (isDebug) {
629
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
630
+ console.debug(`targetOrder`, targetOrder);
631
+ console.debug(
632
+ `[pollOrderStatus] [${orderId}] status=${orderStatus} (elapsed ${elapsed}s)`
633
+ );
634
+ }
635
+ if (["Fulfilled", "Cancelled", "Outdated"].includes(orderStatus)) {
636
+ clearInterval(pollInterval);
637
+ return resolve(orderStatus);
638
+ }
639
+ } catch (error) {
640
+ clearInterval(pollInterval);
641
+ return reject(error);
642
+ }
643
+ }, intervalMs);
644
+ });
645
+ }
646
+
647
+ // src/core/execute/handleOrderPollingResult.ts
648
+ async function handleOrderPollingResult({
649
+ status,
650
+ orderId,
651
+ chainId,
652
+ update,
653
+ messageFor
654
+ }) {
655
+ switch (status) {
656
+ case "Fulfilled":
657
+ update("success", messageFor("success"));
658
+ return {
659
+ status: true,
660
+ orderId,
661
+ chainId,
662
+ finalStatus: status,
663
+ stage: "success"
664
+ };
665
+ case "Cancelled":
666
+ update("error", "Order was cancelled before fulfillment");
667
+ break;
668
+ case "Timeout":
669
+ update("error", "Order polling timed out");
670
+ break;
671
+ case "NotFound":
672
+ default:
673
+ update("error", "Order not found");
674
+ break;
675
+ }
676
+ return {
677
+ status: false,
678
+ orderId,
679
+ chainId,
680
+ finalStatus: status,
681
+ stage: "error"
682
+ };
683
+ }
684
+
685
+ // src/core/execute/ensurePermit2Allowance.ts
686
+ var import_viem5 = require("viem");
687
+ var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
688
+ async function ensurePermit2Allowance({
689
+ chainId,
690
+ tokenIn,
691
+ wallet,
692
+ accountAddress,
693
+ requiredAmount,
694
+ increaseByDelta = false
695
+ }) {
696
+ const spender = import_intents_sdk9.PERMIT2_ADDRESS[chainId];
697
+ let currentAllowance = 0n;
698
+ try {
699
+ if (!wallet.readContract) {
700
+ throw new Error("Wallet does not implement readContract()");
701
+ }
702
+ currentAllowance = await wallet.readContract({
703
+ address: tokenIn,
704
+ abi: import_viem5.erc20Abi,
705
+ functionName: "allowance",
706
+ args: [accountAddress, spender]
707
+ });
708
+ } catch (error) {
709
+ console.warn(`[Permit2] Failed to read allowance for ${tokenIn}`, error);
710
+ }
711
+ const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount : import_viem5.maxUint256;
712
+ console.debug(
713
+ `[Permit2] Approving ${approvalAmount} for ${tokenIn} (current: ${currentAllowance}, required: ${requiredAmount})`
714
+ );
715
+ await wallet.sendTransaction({
716
+ to: tokenIn,
717
+ from: accountAddress,
718
+ data: (0, import_viem5.encodeFunctionData)({
719
+ abi: import_viem5.erc20Abi,
720
+ functionName: "approve",
721
+ args: [spender, approvalAmount]
722
+ }),
723
+ value: 0n
724
+ });
725
+ console.info(
726
+ `[Permit2] Approval transaction sent for ${tokenIn} on chain ${chainId}`
727
+ );
728
+ }
729
+
730
+ // src/core/execute/handleEvmExecution.ts
343
731
  async function handleEvmExecution({
344
732
  recipientAddress,
345
733
  quote,
@@ -347,18 +735,22 @@ async function handleEvmExecution({
347
735
  accountAddress,
348
736
  wallet,
349
737
  isSingleChain,
350
- deadline,
351
- update
738
+ update,
739
+ orderType,
740
+ options
352
741
  }) {
353
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
742
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
743
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
354
744
  await wallet.switchChain(chainId);
355
745
  const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
746
+ quote.tokenOut.address = normalizeEvmTokenAddress(quote.tokenOut.address);
356
747
  const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
357
748
  update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
358
749
  if (shouldWrapNative) {
750
+ quote.tokenIn.address === tokenIn;
359
751
  await wallet.sendTransaction({
360
752
  to: tokenIn,
361
- data: (0, import_viem2.encodeFunctionData)({
753
+ data: (0, import_viem6.encodeFunctionData)({
362
754
  abi: [{ type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] }],
363
755
  functionName: "deposit",
364
756
  args: []
@@ -367,43 +759,70 @@ async function handleEvmExecution({
367
759
  from: accountAddress
368
760
  });
369
761
  }
370
- update("approving", messageFor("approving"));
371
- await wallet.sendTransaction({
372
- to: tokenIn,
373
- data: (0, import_viem2.encodeFunctionData)({
374
- abi: import_viem2.erc20Abi,
375
- functionName: "approve",
376
- args: [import_intents_sdk5.PERMIT2_ADDRESS[chainId], BigInt(quote.amountIn)]
377
- }),
378
- value: 0n,
379
- from: accountAddress
762
+ update("processing", messageFor("approving"));
763
+ await ensurePermit2Allowance({
764
+ chainId,
765
+ tokenIn,
766
+ wallet,
767
+ accountAddress,
768
+ requiredAmount: BigInt(quote.amountIn)
380
769
  });
381
- update("approved", messageFor("approved"));
770
+ update("processing", messageFor("approved"));
382
771
  const destination = recipientAddress ?? accountAddress;
383
772
  const order = await buildOrder({
384
773
  quote,
385
774
  accountAddress,
386
775
  destination,
387
776
  deadline,
388
- isSingleChain
777
+ isSingleChain,
778
+ orderType,
779
+ options
389
780
  });
390
- update("signing", messageFor("signing"));
391
- const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk5.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk5.getEVMCrossChainOrderTypedData)(order);
781
+ console.debug(`order`, order);
782
+ update("processing", messageFor("signing"));
783
+ const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk10.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk10.getEVMCrossChainOrderTypedData)(order);
784
+ const typedData = serializeBigIntsToStrings(orderTypedData);
392
785
  if (!wallet.signTypedData) {
393
786
  throw new Error("Wallet does not support EIP-712 signing");
394
787
  }
395
- const signature = await wallet.signTypedData(serializeBigIntsToStrings(orderTypedData));
396
- update("submitting", messageFor("submitting"));
788
+ const signature = await wallet.signTypedData({
789
+ domain: typedData.domain,
790
+ types: typedData.types,
791
+ primaryType: typedData.primaryType,
792
+ value: typedData.message,
793
+ message: typedData.message
794
+ });
795
+ update("processing", messageFor("submitting"));
397
796
  const res = await order.sendToAuctioneer({ signature, nonce: nonce.toString() });
398
797
  if (!res.success) {
399
798
  throw new Error("Auctioneer submission failed");
400
799
  }
401
- update("success", messageFor("success"));
402
- return { status: true, txHash: res.data, chainId, stage: "success" };
800
+ update("initiated", messageFor("initiated"));
801
+ const { intentId: orderId } = res.data;
802
+ update("initiated", messageFor("shogun_processing"));
803
+ if (orderType === "limit" /* LIMIT */) {
804
+ update("success", messageFor("success_limit"));
805
+ return {
806
+ status: true,
807
+ orderId,
808
+ chainId,
809
+ finalStatus: "OrderPlaced",
810
+ stage: "success"
811
+ };
812
+ } else {
813
+ const status = await pollOrderStatus(accountAddress, orderId, { authToken: options?.authToken });
814
+ return await handleOrderPollingResult({
815
+ status,
816
+ orderId,
817
+ chainId,
818
+ update,
819
+ messageFor
820
+ });
821
+ }
403
822
  }
404
823
 
405
- // src/core/executeOrder/handleSolanaExecution.ts
406
- var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
824
+ // src/core/execute/handleSolanaExecution.ts
825
+ var import_intents_sdk11 = require("@shogun-sdk/intents-sdk");
407
826
  var import_web3 = require("@solana/web3.js");
408
827
  async function handleSolanaExecution({
409
828
  recipientAddress,
@@ -412,12 +831,14 @@ async function handleSolanaExecution({
412
831
  isSingleChain,
413
832
  update,
414
833
  accountAddress,
415
- deadline
834
+ orderType,
835
+ options
416
836
  }) {
417
837
  if (!wallet.rpcUrl) {
418
838
  throw new Error("Solana wallet is missing rpcUrl");
419
839
  }
420
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
840
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
841
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
421
842
  update("processing", messageFor("processing"));
422
843
  const destination = recipientAddress ?? accountAddress;
423
844
  const order = await buildOrder({
@@ -425,7 +846,9 @@ async function handleSolanaExecution({
425
846
  accountAddress,
426
847
  destination,
427
848
  deadline,
428
- isSingleChain
849
+ isSingleChain,
850
+ orderType,
851
+ options
429
852
  });
430
853
  const txData = await getSolanaOrderInstructions({
431
854
  order,
@@ -433,10 +856,9 @@ async function handleSolanaExecution({
433
856
  rpcUrl: wallet.rpcUrl
434
857
  });
435
858
  const transaction = import_web3.VersionedTransaction.deserialize(Uint8Array.from(txData.txBytes));
436
- update("signing", messageFor("signing"));
437
- console.log({ order });
438
- const txSignature = await wallet.sendTransaction(transaction);
439
- update("submitting", messageFor("submitting"));
859
+ update("processing", messageFor("signing"));
860
+ await wallet.sendTransaction(transaction);
861
+ update("processing", messageFor("submitting"));
440
862
  const response = await submitToAuctioneer({
441
863
  order,
442
864
  isSingleChain,
@@ -445,25 +867,40 @@ async function handleSolanaExecution({
445
867
  if (!response.success) {
446
868
  throw new Error("Auctioneer submission failed");
447
869
  }
448
- update("success", messageFor("success"));
449
- return {
450
- status: true,
451
- txHash: txSignature,
452
- chainId: import_intents_sdk6.ChainID.Solana,
453
- stage: "success"
454
- };
455
- }
456
- async function getSolanaOrderInstructions({
870
+ update("initiated", messageFor("initiated"));
871
+ const { intentId: orderId } = response.data;
872
+ update("initiated", messageFor("shogun_processing"));
873
+ if (orderType === "limit" /* LIMIT */) {
874
+ update("success", messageFor("success_limit"));
875
+ return {
876
+ status: true,
877
+ orderId,
878
+ chainId: SOLANA_CHAIN_ID,
879
+ finalStatus: "OrderPlaced",
880
+ stage: "success"
881
+ };
882
+ } else {
883
+ const status = await pollOrderStatus(accountAddress, orderId, { authToken: options?.authToken });
884
+ return await handleOrderPollingResult({
885
+ status,
886
+ orderId,
887
+ chainId: SOLANA_CHAIN_ID,
888
+ update,
889
+ messageFor
890
+ });
891
+ }
892
+ }
893
+ async function getSolanaOrderInstructions({
457
894
  order,
458
895
  isSingleChain,
459
896
  rpcUrl
460
897
  }) {
461
898
  if (isSingleChain) {
462
- return await (0, import_intents_sdk6.getSolanaSingleChainOrderInstructions)(order, {
899
+ return await (0, import_intents_sdk11.getSolanaSingleChainOrderInstructions)(order, {
463
900
  rpcUrl
464
901
  });
465
902
  }
466
- return await (0, import_intents_sdk6.getSolanaCrossChainOrderInstructions)(order, {
903
+ return await (0, import_intents_sdk11.getSolanaCrossChainOrderInstructions)(order, {
467
904
  rpcUrl
468
905
  });
469
906
  }
@@ -484,52 +921,93 @@ async function submitToAuctioneer({
484
921
  });
485
922
  }
486
923
 
487
- // src/core/executeOrder/execute.ts
924
+ // src/core/execute/execute.ts
488
925
  async function executeOrder({
489
926
  quote,
490
927
  accountAddress,
491
928
  recipientAddress,
492
929
  wallet,
493
930
  onStatus,
931
+ orderType = "market" /* MARKET */,
494
932
  options = {}
495
933
  }) {
496
- const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
934
+ const isDev = process.env.NODE_ENV !== "production";
935
+ const log = (...args) => {
936
+ if (isDev) console.debug("[OneShot::executeOrder]", ...args);
937
+ };
497
938
  const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
498
- const update = (stage, message) => onStatus?.(stage, message ?? messageFor(stage));
939
+ const update = (stage, message) => {
940
+ log("Stage:", stage, "| Message:", message ?? messageFor(stage));
941
+ onStatus?.(stage, message ?? messageFor(stage));
942
+ };
499
943
  try {
944
+ log("Starting execution:", {
945
+ accountAddress,
946
+ recipientAddress,
947
+ tokenIn: quote?.tokenIn,
948
+ tokenOut: quote?.tokenOut
949
+ });
500
950
  const adapter = normalizeWallet(wallet);
501
951
  if (!adapter) throw new Error("No wallet provided");
502
952
  const { tokenIn, tokenOut } = quote;
953
+ const srcChain = Number(tokenIn.chainId);
954
+ const destChain = Number(tokenOut.chainId);
955
+ if (!CURRENT_SUPPORTED.includes(srcChain) || !CURRENT_SUPPORTED.includes(destChain)) {
956
+ const unsupportedChains = [
957
+ !CURRENT_SUPPORTED.includes(srcChain) ? srcChain : null,
958
+ !CURRENT_SUPPORTED.includes(destChain) ? destChain : null
959
+ ].filter(Boolean).join(", ");
960
+ const errorMsg = `Unsupported chain(s): ${unsupportedChains}`;
961
+ update("error", errorMsg);
962
+ log("Error:", errorMsg);
963
+ throw new Error(errorMsg);
964
+ }
503
965
  const isSingleChain = tokenIn.chainId === tokenOut.chainId;
504
966
  const chainId = Number(tokenIn.chainId);
505
- update("processing", messageFor("processing"));
506
- if ((0, import_intents_sdk7.isEvmChain)(chainId)) {
507
- return await handleEvmExecution({
967
+ update("processing");
968
+ if ((0, import_intents_sdk12.isEvmChain)(chainId)) {
969
+ log("Detected EVM chain:", chainId);
970
+ const result = await handleEvmExecution({
508
971
  recipientAddress,
509
972
  quote,
510
973
  chainId,
511
974
  accountAddress,
512
975
  wallet: adapter,
513
976
  isSingleChain,
514
- deadline,
515
- update
977
+ update,
978
+ orderType,
979
+ options
516
980
  });
981
+ log("EVM execution result:", result);
982
+ return result;
517
983
  }
518
- if (chainId === import_intents_sdk7.ChainID.Solana) {
519
- return await handleSolanaExecution({
984
+ if (chainId === import_intents_sdk12.ChainID.Solana) {
985
+ log("Detected Solana chain");
986
+ const result = await handleSolanaExecution({
520
987
  recipientAddress,
521
988
  quote,
522
989
  accountAddress,
523
990
  wallet: adapter,
524
991
  isSingleChain,
525
- deadline,
526
- update
992
+ update,
993
+ orderType,
994
+ options
527
995
  });
996
+ log("Solana execution result:", result);
997
+ return result;
528
998
  }
529
- update("error", "Unsupported chain");
530
- return { status: false, message: "Unsupported chain", stage: "error" };
999
+ const unsupported = `Unsupported chain: ${chainId}`;
1000
+ update("error", unsupported);
1001
+ log("Error:", unsupported);
1002
+ return { status: false, message: unsupported, stage: "error" };
531
1003
  } catch (error) {
532
- const message = error instanceof import_viem3.BaseError ? error.shortMessage : error instanceof Error ? error.message : String(error);
1004
+ let message = "An unknown error occurred";
1005
+ if (error && typeof error === "object") {
1006
+ const err = error;
1007
+ message = err.details ?? err.message ?? message;
1008
+ } else if (typeof error === "string") {
1009
+ message = error;
1010
+ }
533
1011
  update("error", message);
534
1012
  return { status: false, message, stage: "error" };
535
1013
  }
@@ -540,349 +1018,972 @@ function normalizeWallet(wallet) {
540
1018
  return wallet;
541
1019
  }
542
1020
 
543
- // src/react/useExecuteOrder.ts
544
- function useExecuteOrder() {
545
- const [status, setStatus] = (0, import_react2.useState)("processing");
546
- const [message, setMessage] = (0, import_react2.useState)(null);
547
- const [loading, setLoading] = (0, import_react2.useState)(false);
548
- const [data, setData] = (0, import_react2.useState)(null);
549
- const [error, setError] = (0, import_react2.useState)(null);
550
- const isMounted = (0, import_react2.useRef)(true);
1021
+ // src/core/orders/getOrders.ts
1022
+ var import_intents_sdk13 = require("@shogun-sdk/intents-sdk");
1023
+ async function getOrders({
1024
+ evmAddress,
1025
+ solAddress
1026
+ }) {
1027
+ const wallets = [evmAddress, solAddress].filter(
1028
+ (wallet) => Boolean(wallet)
1029
+ );
1030
+ if (wallets.length === 0) {
1031
+ throw new Error("At least one wallet address (EVM, Solana) must be provided.");
1032
+ }
1033
+ const results = await Promise.all(
1034
+ wallets.map((wallet) => (0, import_intents_sdk13.fetchUserOrders)({ wallet }))
1035
+ );
1036
+ return results.reduce(
1037
+ (merged, orders) => {
1038
+ merged.singleChainLimitOrders.push(...orders.singleChainLimitOrders);
1039
+ merged.crossChainLimitOrders.push(...orders.crossChainLimitOrders);
1040
+ return merged;
1041
+ },
1042
+ { singleChainLimitOrders: [], crossChainLimitOrders: [] }
1043
+ );
1044
+ }
1045
+
1046
+ // src/core/orders/cancelOrder.ts
1047
+ var import_intents_sdk14 = require("@shogun-sdk/intents-sdk");
1048
+ var import_web32 = require("@solana/web3.js");
1049
+ var import_viem8 = require("viem");
1050
+ var inFlightCancels = /* @__PURE__ */ new Map();
1051
+ function cancelIntentsOrder(args) {
1052
+ const srcChain = "srcChainId" in args.order ? args.order.srcChainId : args.order.chainId;
1053
+ const key = `${srcChain}:${args.order.orderId}`;
1054
+ const existing = inFlightCancels.get(key);
1055
+ if (existing) return existing;
1056
+ const pending = performCancel(args).finally(() => {
1057
+ inFlightCancels.delete(key);
1058
+ });
1059
+ inFlightCancels.set(key, pending);
1060
+ return pending;
1061
+ }
1062
+ async function performCancel({
1063
+ order,
1064
+ wallet,
1065
+ sol_rpc
1066
+ }) {
1067
+ const isCrossChain = "srcChainId" in order && "destChainId" in order && order.srcChainId !== order.destChainId;
1068
+ const srcChain = "srcChainId" in order ? order.srcChainId : order.chainId;
1069
+ const isSolanaOrder = srcChain === import_intents_sdk14.ChainID.Solana;
1070
+ if (isSolanaOrder) {
1071
+ if (!isCrossChain) {
1072
+ const { versionedMessageBytes: versionedMessageBytes2 } = await (0, import_intents_sdk14.cancelSingleChainOrderInstructionsAsBytes)(
1073
+ order.orderId,
1074
+ order.user,
1075
+ { rpcUrl: sol_rpc }
1076
+ );
1077
+ const message2 = import_web32.VersionedMessage.deserialize(
1078
+ versionedMessageBytes2
1079
+ );
1080
+ const tx2 = new import_web32.VersionedTransaction(message2);
1081
+ return await wallet.sendTransaction(tx2);
1082
+ }
1083
+ const { versionedMessageBytes } = await (0, import_intents_sdk14.cancelCrossChainOrderInstructionsAsBytes)(
1084
+ order.orderId,
1085
+ order.user,
1086
+ { rpcUrl: sol_rpc }
1087
+ );
1088
+ const message = import_web32.VersionedMessage.deserialize(
1089
+ versionedMessageBytes
1090
+ );
1091
+ const tx = new import_web32.VersionedTransaction(message);
1092
+ return await wallet.sendTransaction(tx);
1093
+ }
1094
+ const chainId = srcChain;
1095
+ const { readContract } = wallet;
1096
+ if (!readContract) {
1097
+ throw new Error("Wallet does not support readContract");
1098
+ }
1099
+ const nonce = BigInt(order.nonce ?? "0");
1100
+ const nonceWordPos = nonce >> 8n;
1101
+ const nonceBitPos = nonce - nonceWordPos * 256n;
1102
+ if (isCrossChain) {
1103
+ const [orderData = [false, false], currentNonceBitmap = 0n] = await Promise.all([
1104
+ readContract({
1105
+ address: import_intents_sdk14.CROSS_CHAIN_GUARD_ADDRESSES[chainId],
1106
+ abi: [
1107
+ {
1108
+ inputs: [{ name: "orderId", type: "bytes32" }],
1109
+ name: "orderData",
1110
+ outputs: [
1111
+ { name: "initialized", type: "bool" },
1112
+ { name: "deactivated", type: "bool" }
1113
+ ],
1114
+ stateMutability: "view",
1115
+ type: "function"
1116
+ }
1117
+ ],
1118
+ functionName: "orderData",
1119
+ args: [order.orderId]
1120
+ }),
1121
+ readContract({
1122
+ address: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1123
+ abi: [
1124
+ {
1125
+ inputs: [
1126
+ { name: "owner", type: "address" },
1127
+ { name: "wordPos", type: "uint256" }
1128
+ ],
1129
+ name: "nonceBitmap",
1130
+ outputs: [{ name: "", type: "uint256" }],
1131
+ stateMutability: "view",
1132
+ type: "function"
1133
+ }
1134
+ ],
1135
+ functionName: "nonceBitmap",
1136
+ args: [order.user, nonceWordPos]
1137
+ })
1138
+ ]);
1139
+ const [initialized, deactivated] = orderData;
1140
+ if (initialized) {
1141
+ if (deactivated) {
1142
+ throw new Error("Order is already deactivated");
1143
+ }
1144
+ return await wallet.sendTransaction({
1145
+ to: import_intents_sdk14.CROSS_CHAIN_GUARD_ADDRESSES[order.srcChainId],
1146
+ data: (0, import_viem8.encodeFunctionData)({
1147
+ abi: [
1148
+ {
1149
+ inputs: [
1150
+ {
1151
+ components: [
1152
+ { name: "user", type: "address" },
1153
+ { name: "tokenIn", type: "address" },
1154
+ { name: "srcChainId", type: "uint256" },
1155
+ { name: "deadline", type: "uint256" },
1156
+ { name: "amountIn", type: "uint256" },
1157
+ { name: "minStablecoinsAmount", type: "uint256" },
1158
+ { name: "executionDetailsHash", type: "bytes32" },
1159
+ { name: "nonce", type: "uint256" }
1160
+ ],
1161
+ name: "orderInfo",
1162
+ type: "tuple"
1163
+ }
1164
+ ],
1165
+ name: "cancelOrder",
1166
+ outputs: [],
1167
+ stateMutability: "nonpayable",
1168
+ type: "function"
1169
+ }
1170
+ ],
1171
+ functionName: "cancelOrder",
1172
+ args: [
1173
+ {
1174
+ user: order.user,
1175
+ tokenIn: order.tokenIn,
1176
+ srcChainId: BigInt(order.srcChainId),
1177
+ deadline: BigInt(order.deadline),
1178
+ amountIn: BigInt(order.amountIn),
1179
+ minStablecoinsAmount: BigInt(order.minStablecoinsAmount),
1180
+ executionDetailsHash: order.executionDetailsHash,
1181
+ nonce
1182
+ }
1183
+ ]
1184
+ }),
1185
+ value: BigInt(0),
1186
+ from: order.user
1187
+ });
1188
+ } else {
1189
+ if ((currentNonceBitmap & 1n << nonceBitPos) !== 0n) {
1190
+ throw new Error("Nonce is already invalidated");
1191
+ }
1192
+ const mask2 = 1n << nonceBitPos;
1193
+ return await wallet.sendTransaction({
1194
+ to: import_intents_sdk14.PERMIT2_ADDRESS[order.srcChainId],
1195
+ data: (0, import_viem8.encodeFunctionData)({
1196
+ abi: [
1197
+ {
1198
+ inputs: [
1199
+ { name: "wordPos", type: "uint256" },
1200
+ { name: "mask", type: "uint256" }
1201
+ ],
1202
+ name: "invalidateUnorderedNonces",
1203
+ outputs: [],
1204
+ stateMutability: "nonpayable",
1205
+ type: "function"
1206
+ }
1207
+ ],
1208
+ functionName: "invalidateUnorderedNonces",
1209
+ args: [nonceWordPos, mask2]
1210
+ }),
1211
+ value: BigInt(0),
1212
+ from: order.user
1213
+ });
1214
+ }
1215
+ }
1216
+ const [wasManuallyInitialized, currentBitmap = 0n] = await Promise.all([
1217
+ readContract({
1218
+ address: import_intents_sdk14.SINGLE_CHAIN_GUARD_ADDRESSES[chainId],
1219
+ abi: [
1220
+ {
1221
+ inputs: [{ name: "orderHash", type: "bytes32" }],
1222
+ name: "orderManuallyInitialized",
1223
+ outputs: [{ name: "", type: "bool" }],
1224
+ stateMutability: "view",
1225
+ type: "function"
1226
+ }
1227
+ ],
1228
+ functionName: "orderManuallyInitialized",
1229
+ args: [order.orderId]
1230
+ }),
1231
+ readContract({
1232
+ address: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1233
+ abi: [
1234
+ {
1235
+ inputs: [
1236
+ { name: "owner", type: "address" },
1237
+ { name: "wordPos", type: "uint256" }
1238
+ ],
1239
+ name: "nonceBitmap",
1240
+ outputs: [{ name: "", type: "uint256" }],
1241
+ stateMutability: "view",
1242
+ type: "function"
1243
+ }
1244
+ ],
1245
+ functionName: "nonceBitmap",
1246
+ args: [order.user, nonceWordPos]
1247
+ })
1248
+ ]);
1249
+ if (wasManuallyInitialized) {
1250
+ return await wallet.sendTransaction({
1251
+ to: import_intents_sdk14.SINGLE_CHAIN_GUARD_ADDRESSES[chainId],
1252
+ data: (0, import_viem8.encodeFunctionData)({
1253
+ abi: [
1254
+ {
1255
+ inputs: [
1256
+ {
1257
+ name: "order",
1258
+ type: "tuple",
1259
+ components: [
1260
+ { name: "amountIn", type: "uint256" },
1261
+ { name: "tokenIn", type: "address" },
1262
+ { name: "deadline", type: "uint256" },
1263
+ { name: "nonce", type: "uint256" },
1264
+ { name: "encodedExternalCallData", type: "bytes" },
1265
+ {
1266
+ name: "extraTransfers",
1267
+ type: "tuple[]",
1268
+ components: [
1269
+ { name: "amount", type: "uint256" },
1270
+ { name: "receiver", type: "address" },
1271
+ { name: "token", type: "address" }
1272
+ ]
1273
+ },
1274
+ {
1275
+ name: "requestedOutput",
1276
+ type: "tuple",
1277
+ components: [
1278
+ { name: "amount", type: "uint256" },
1279
+ { name: "receiver", type: "address" },
1280
+ { name: "token", type: "address" }
1281
+ ]
1282
+ },
1283
+ { name: "user", type: "address" }
1284
+ ]
1285
+ }
1286
+ ],
1287
+ name: "cancelManuallyCreatedOrder",
1288
+ outputs: [],
1289
+ stateMutability: "nonpayable",
1290
+ type: "function"
1291
+ }
1292
+ ],
1293
+ functionName: "cancelManuallyCreatedOrder",
1294
+ args: [
1295
+ {
1296
+ amountIn: BigInt(order.amountIn),
1297
+ tokenIn: order.tokenIn,
1298
+ deadline: BigInt(order.deadline),
1299
+ nonce,
1300
+ encodedExternalCallData: "0x",
1301
+ extraTransfers: (order.extraTransfers || []).map((t) => ({
1302
+ amount: BigInt(t.amount),
1303
+ receiver: t.receiver,
1304
+ token: t.token
1305
+ })),
1306
+ requestedOutput: {
1307
+ amount: BigInt(order.amountOutMin),
1308
+ receiver: order.destinationAddress,
1309
+ token: order.tokenOut
1310
+ },
1311
+ user: order.user
1312
+ }
1313
+ ]
1314
+ }),
1315
+ value: 0n,
1316
+ from: order.user
1317
+ });
1318
+ }
1319
+ const mask = 1n << nonceBitPos;
1320
+ if ((currentBitmap & mask) !== 0n) {
1321
+ throw new Error("Nonce is already invalidated");
1322
+ }
1323
+ return await wallet.sendTransaction({
1324
+ to: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1325
+ data: (0, import_viem8.encodeFunctionData)({
1326
+ abi: [
1327
+ {
1328
+ inputs: [
1329
+ { name: "wordPos", type: "uint256" },
1330
+ { name: "mask", type: "uint256" }
1331
+ ],
1332
+ name: "invalidateUnorderedNonces",
1333
+ outputs: [],
1334
+ stateMutability: "nonpayable",
1335
+ type: "function"
1336
+ }
1337
+ ],
1338
+ functionName: "invalidateUnorderedNonces",
1339
+ args: [nonceWordPos, mask]
1340
+ }),
1341
+ value: 0n,
1342
+ from: order.user
1343
+ });
1344
+ }
1345
+
1346
+ // src/core/client.ts
1347
+ var SwapSDK = class {
1348
+ constructor(config) {
1349
+ __publicField(this, "apiKey");
1350
+ /**
1351
+ * Fetches metadata for one or more tokens from the Shogun Token Search API.
1352
+ *
1353
+ * ---
1354
+ * ### Overview
1355
+ * `getTokensData` retrieves normalized token information — such as symbol, name,
1356
+ * decimals, logo URI, and verified status — for a given list of token addresses.
1357
+ *
1358
+ * It supports both **EVM** and **SVM (Solana)** tokens, returning metadata from
1359
+ * Shogun’s unified token registry.
1360
+ *
1361
+ * ---
1362
+ * @example
1363
+ * ```ts
1364
+ * const tokens = await getTokensData([
1365
+ * "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
1366
+ * "So11111111111111111111111111111111111111112", // SOL
1367
+ * ]);
1368
+ *
1369
+ * console.log(tokens);
1370
+ * [
1371
+ * { symbol: "USDC", name: "USD Coin", chainId: 1, decimals: 6, ... },
1372
+ * { symbol: "SOL", name: "Solana", chainId: 101, decimals: 9, ... }
1373
+ * ]
1374
+ * ```
1375
+ *
1376
+ * @param addresses - An array of token addresses (EVM or SVM) to fetch metadata for.
1377
+ * @returns A promise resolving to an array of {@link TokenInfo} objects.
1378
+ *
1379
+ * @throws Will throw an error if the network request fails or the API responds with a non-OK status.
1380
+ */
1381
+ __publicField(this, "getTokensData", getTokensData.bind(this));
1382
+ if (!config.apiKey) {
1383
+ throw new Error("SwapSDK: Missing API key");
1384
+ }
1385
+ this.apiKey = config.apiKey;
1386
+ if (this.apiKey) void this.apiKey;
1387
+ }
1388
+ /**
1389
+ * Retrieves a swap quote for the given input and output tokens.
1390
+ *
1391
+ * @param params - Quote parameters including source/destination tokens and amount.
1392
+ * @returns A normalized `SwapQuoteResponse` containing output amount, route, and metadata.
1393
+ */
1394
+ async getQuote(params) {
1395
+ return getQuote(params);
1396
+ }
1397
+ /**
1398
+ * Fetches token balances for the specified user wallet(s).
1399
+ *
1400
+ * Supports both EVM and SVM (Solana) wallet addresses.
1401
+ *
1402
+ * @param params - Wallet address and optional chain filters.
1403
+ * @param options - Optional abort signal for cancellation.
1404
+ * @returns A unified balance response with per-chain token details.
1405
+ */
1406
+ async getBalances(params, options) {
1407
+ return getBalances(params, options);
1408
+ }
1409
+ /**
1410
+ * Retrieves a list of verified tokens based on search query or chain filter.
1411
+ *
1412
+ * @param params - Search parameters (query, chain ID, pagination options).
1413
+ * @returns Paginated `TokenSearchResponse` containing token metadata.
1414
+ */
1415
+ async getTokenList(params) {
1416
+ return getTokenList(params);
1417
+ }
1418
+ /**
1419
+ * Executes a prepared swap quote using the provided wallet and configuration.
1420
+ *
1421
+ * Handles:
1422
+ * - Token approval (if required)
1423
+ * - Transaction signing and broadcasting
1424
+ * - Confirmation polling and stage-based status updates
1425
+ *
1426
+ * Supports both:
1427
+ * - Market orders (with optional deadline)
1428
+ * - Limit orders (requires executionPrice and deadline)
1429
+ *
1430
+ * @param quote - The swap quote to execute, containing route and metadata.
1431
+ * @param accountAddress - The user's wallet address executing the swap.
1432
+ * @param recipientAddress - Optional recipient address for the output tokens (defaults to sender).
1433
+ * @param wallet - Adapted wallet instance (EVM/Solana) or a standard Viem `WalletClient`.
1434
+ * @param onStatus - Optional callback for receiving execution stage updates and messages.
1435
+ * @param orderType - Defines whether this is a market or limit order.
1436
+ * @param options - Execution parameters (different per order type).
1437
+ *
1438
+ * @returns A finalized execution result containing transaction hash, status, and any returned data.
1439
+ *
1440
+ * @example
1441
+ * ```ts
1442
+ * * Market order
1443
+ * const result = await sdk.executeTransaction({
1444
+ * quote,
1445
+ * accountAddress: "0x123...",
1446
+ * wallet,
1447
+ * orderType: OrderExecutionType.MARKET,
1448
+ * options: { deadline: 1800 },
1449
+ * onStatus: (stage, msg) => console.log(stage, msg),
1450
+ * });
1451
+ *
1452
+ * * Limit order
1453
+ * const result = await sdk.executeTransaction({
1454
+ * quote,
1455
+ * accountAddress: "0x123...",
1456
+ * wallet,
1457
+ * orderType: OrderExecutionType.LIMIT,
1458
+ * options: { executionPrice: "0.0021", deadline: 3600 },
1459
+ * });
1460
+ * ```
1461
+ */
1462
+ async executeTransaction({
1463
+ quote,
1464
+ accountAddress,
1465
+ recipientAddress,
1466
+ wallet,
1467
+ onStatus,
1468
+ orderType,
1469
+ options
1470
+ }) {
1471
+ return executeOrder({
1472
+ quote,
1473
+ wallet,
1474
+ accountAddress,
1475
+ recipientAddress,
1476
+ onStatus,
1477
+ orderType,
1478
+ options
1479
+ });
1480
+ }
1481
+ /**
1482
+ * Fetches all user orders (Market, Limit, Cross-chain) for connected wallets.
1483
+ *
1484
+ * ---
1485
+ * ### Overview
1486
+ * Retrieves both **single-chain** and **cross-chain** orders from the Shogun Intents API.
1487
+ * Works across EVM, Solana
1488
+ *
1489
+ * ---
1490
+ * @example
1491
+ * ```ts
1492
+ * const orders = await sdk.getOrders({
1493
+ * evmAddress: "0x123...",
1494
+ * solAddress: "9d12hF...abc",
1495
+ * });
1496
+ *
1497
+ * console.log(orders.singleChainLimitOrders);
1498
+ * ```
1499
+ *
1500
+ * @param params - Wallet addresses to fetch orders for (EVM, Solana).
1501
+ * @returns A structured {@link ApiUserOrders} object containing all user orders.
1502
+ */
1503
+ async getOrders(params) {
1504
+ return getOrders(params);
1505
+ }
1506
+ /**
1507
+ * Cancels an order (single-chain or cross-chain) on EVM or Solana.
1508
+ *
1509
+ * Internally routes to the correct guard contract or Solana program to
1510
+ * deactivate the order or invalidate its nonce.
1511
+ *
1512
+ * @param params.order - Order payload returned from the Intents API.
1513
+ * @param params.wallet - Adapted wallet used to submit the cancellation transaction.
1514
+ * @param params.solRpc - Solana RPC URL used for SVM cancellations.
1515
+ *
1516
+ * @returns A transaction signature or hash from the underlying wallet.
1517
+ */
1518
+ async cancelOrder(params) {
1519
+ return cancelIntentsOrder({
1520
+ order: params.order,
1521
+ wallet: params.wallet,
1522
+ sol_rpc: params.solRpc
1523
+ });
1524
+ }
1525
+ };
1526
+
1527
+ // src/react/SwapProvider.tsx
1528
+ var import_jsx_runtime = require("react/jsx-runtime");
1529
+ var SwapContext = (0, import_react.createContext)(null);
1530
+ var SwapProvider = ({ config, children }) => {
1531
+ const sdk = (0, import_react.useMemo)(() => new SwapSDK(config), [config.apiKey]);
1532
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwapContext.Provider, { value: sdk, children });
1533
+ };
1534
+ var useSwap = () => {
1535
+ const ctx = (0, import_react.useContext)(SwapContext);
1536
+ if (!ctx) {
1537
+ throw new Error("useSwap must be used within <SwapProvider>");
1538
+ }
1539
+ return ctx;
1540
+ };
1541
+
1542
+ // src/react/useQuote.ts
1543
+ var import_react2 = require("react");
1544
+ var import_swr = __toESM(require("swr"), 1);
1545
+ var QUOTE_KEY = "quote-global";
1546
+ function isValidQuoteParams(p) {
1547
+ if (!p) return false;
1548
+ const { tokenIn, tokenOut, amount } = p;
1549
+ if (!tokenIn || !tokenOut || !amount) return false;
1550
+ const n = Number(amount);
1551
+ return Number.isFinite(n) && n > 0;
1552
+ }
1553
+ function useQuote(initialParams) {
1554
+ const sdk = useSwap();
1555
+ const abortRef = (0, import_react2.useRef)(null);
1556
+ const paramsRef = globalThis.__QUOTE_PARAMS_REF__ ?? (globalThis.__QUOTE_PARAMS_REF__ = { current: initialParams ?? null });
551
1557
  (0, import_react2.useEffect)(() => {
552
- return () => {
553
- isMounted.current = false;
554
- };
555
- }, []);
556
- const execute = (0, import_react2.useCallback)(
1558
+ if (initialParams && JSON.stringify(paramsRef.current) !== JSON.stringify(initialParams)) {
1559
+ paramsRef.current = initialParams;
1560
+ void (0, import_swr.mutate)(QUOTE_KEY);
1561
+ }
1562
+ }, [initialParams]);
1563
+ const fetcher = (0, import_react2.useCallback)(async () => {
1564
+ const activeParams = paramsRef.current;
1565
+ if (!isValidQuoteParams(activeParams)) return null;
1566
+ if (abortRef.current) abortRef.current.abort();
1567
+ const controller = new AbortController();
1568
+ abortRef.current = controller;
1569
+ try {
1570
+ return await sdk.getQuote(activeParams);
1571
+ } catch (err) {
1572
+ if (err instanceof DOMException && err.name === "AbortError") return null;
1573
+ if (err instanceof Error) throw err;
1574
+ throw new Error(String(err));
1575
+ }
1576
+ }, [sdk]);
1577
+ const {
1578
+ data,
1579
+ error,
1580
+ isValidating: loading,
1581
+ mutate: mutateQuote
1582
+ } = (0, import_swr.default)(QUOTE_KEY, fetcher, {
1583
+ revalidateOnFocus: false,
1584
+ shouldRetryOnError: false,
1585
+ keepPreviousData: true
1586
+ });
1587
+ const refetch = (0, import_react2.useCallback)(async () => {
1588
+ await mutateQuote();
1589
+ }, [mutateQuote]);
1590
+ const setParams = (0, import_react2.useCallback)(
1591
+ (next) => {
1592
+ paramsRef.current = next;
1593
+ void (0, import_swr.mutate)(QUOTE_KEY);
1594
+ },
1595
+ []
1596
+ );
1597
+ return (0, import_react2.useMemo)(
1598
+ () => ({
1599
+ data,
1600
+ loading,
1601
+ error: error instanceof Error ? error.message : null,
1602
+ refetch,
1603
+ setParams,
1604
+ get activeParams() {
1605
+ return paramsRef.current;
1606
+ }
1607
+ }),
1608
+ [data, loading, error, refetch, setParams]
1609
+ );
1610
+ }
1611
+
1612
+ // src/react/useExecuteTransaction.ts
1613
+ var import_react4 = require("react");
1614
+
1615
+ // src/react/useBalances.ts
1616
+ var import_react3 = require("react");
1617
+ var import_swr2 = __toESM(require("swr"), 1);
1618
+ var BALANCE_KEY = "balances-global";
1619
+ function useBalances(initialParams, options) {
1620
+ const sdk = useSwap();
1621
+ const abortRef = (0, import_react3.useRef)(null);
1622
+ const lastDataRef = (0, import_react3.useRef)(null);
1623
+ const paramsRef = globalThis.__BALANCES_PARAMS_REF__ ?? (globalThis.__BALANCES_PARAMS_REF__ = { current: initialParams ?? null });
1624
+ const fetcher = (0, import_react3.useCallback)(async () => {
1625
+ const activeParams = paramsRef.current;
1626
+ if (!activeParams) return null;
1627
+ if (abortRef.current) abortRef.current.abort();
1628
+ const controller = new AbortController();
1629
+ abortRef.current = controller;
1630
+ try {
1631
+ const balances = await sdk.getBalances(activeParams, { signal: controller.signal });
1632
+ lastDataRef.current = balances;
1633
+ return balances;
1634
+ } catch (err) {
1635
+ if (err instanceof DOMException && err.name === "AbortError") return lastDataRef.current;
1636
+ if (err instanceof Error) throw err;
1637
+ throw new Error(String(err));
1638
+ }
1639
+ }, [sdk, paramsRef]);
1640
+ const {
1641
+ data,
1642
+ error,
1643
+ // `isLoading` is only true on the initial fetch (no data yet), so background
1644
+ // refreshes on `refreshInterval` don't toggle it and flicker the UI.
1645
+ isLoading: loading,
1646
+ isValidating,
1647
+ mutate: mutateBalances
1648
+ } = (0, import_swr2.default)(BALANCE_KEY, fetcher, {
1649
+ revalidateOnFocus: false,
1650
+ shouldRetryOnError: false,
1651
+ keepPreviousData: true,
1652
+ // 0 (default) disables polling; a positive value re-fetches on that interval.
1653
+ refreshInterval: options?.refreshInterval ?? 0
1654
+ });
1655
+ const refetch = (0, import_react3.useCallback)(async () => {
1656
+ await mutateBalances();
1657
+ }, [mutateBalances]);
1658
+ const setParams = (0, import_react3.useCallback)((next) => {
1659
+ paramsRef.current = next;
1660
+ void (0, import_swr2.mutate)(BALANCE_KEY);
1661
+ }, [paramsRef]);
1662
+ (0, import_react3.useEffect)(() => {
1663
+ if (initialParams) {
1664
+ const prevParams = paramsRef.current;
1665
+ const paramsChanged = !prevParams || prevParams.addresses.svm !== initialParams.addresses.svm || prevParams.addresses.evm !== initialParams.addresses.evm;
1666
+ if (paramsChanged) {
1667
+ paramsRef.current = initialParams;
1668
+ void (0, import_swr2.mutate)(BALANCE_KEY);
1669
+ }
1670
+ }
1671
+ }, [initialParams, paramsRef]);
1672
+ return (0, import_react3.useMemo)(
1673
+ () => ({
1674
+ data,
1675
+ loading,
1676
+ // True during background revalidation (e.g. `refreshInterval` polls) while
1677
+ // previous `data` stays visible — use for a subtle refresh indicator.
1678
+ isValidating,
1679
+ error: error instanceof Error ? error : null,
1680
+ refetch,
1681
+ setParams,
1682
+ get activeParams() {
1683
+ return paramsRef.current;
1684
+ }
1685
+ }),
1686
+ [data, loading, isValidating, error, refetch, setParams, paramsRef]
1687
+ );
1688
+ }
1689
+
1690
+ // src/react/useExecuteTransaction.ts
1691
+ function useExecuteTransaction() {
1692
+ const sdk = useSwap();
1693
+ const [isLoading, setLoading] = (0, import_react4.useState)(false);
1694
+ const [stage, setStage] = (0, import_react4.useState)(null);
1695
+ const [message, setMessage] = (0, import_react4.useState)(null);
1696
+ const [error, setError] = (0, import_react4.useState)(null);
1697
+ const [result, setResult] = (0, import_react4.useState)(null);
1698
+ const { refetch: refetchQuote } = useQuote();
1699
+ const { refetch: refetchBalances } = useBalances();
1700
+ const execute = (0, import_react4.useCallback)(
557
1701
  async ({
558
1702
  quote,
559
1703
  accountAddress,
560
1704
  recipientAddress,
561
1705
  wallet,
562
- deadline
1706
+ orderType,
1707
+ options
563
1708
  }) => {
564
- if (!quote || !wallet) {
565
- throw new Error("Quote and wallet are required for order execution.");
566
- }
567
1709
  setLoading(true);
568
1710
  setError(null);
569
- setData(null);
570
- setMessage(null);
1711
+ setResult(null);
1712
+ const onStatus = (s, msg) => {
1713
+ setStage(s);
1714
+ setMessage(msg ?? "");
1715
+ };
571
1716
  try {
572
- const effectiveDeadline = deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
573
- const onStatus = (stage, msg) => {
574
- if (!isMounted.current) return;
575
- setStatus(stage);
576
- if (msg) setMessage(msg);
577
- };
578
- const result = await executeOrder({
1717
+ const res = await sdk.executeTransaction({
579
1718
  quote,
1719
+ wallet,
580
1720
  accountAddress,
581
1721
  recipientAddress,
582
- wallet,
583
1722
  onStatus,
584
- options: { deadline: effectiveDeadline }
1723
+ orderType,
1724
+ options
585
1725
  });
586
- if (!isMounted.current) return result;
587
- setData(result);
588
- setStatus(result.stage);
589
- setMessage("Order executed successfully");
590
- return result;
591
- } catch (err) {
592
- const errorObj = err instanceof Error ? err : new Error(String(err));
593
- if (isMounted.current) {
594
- setError(errorObj);
595
- setStatus("error");
596
- setMessage(errorObj.message);
597
- setData({
598
- status: false,
599
- stage: "error",
600
- message: errorObj.message
1726
+ if (res && typeof res === "object" && "status" in res && "stage" in res && typeof res.stage === "string") {
1727
+ setResult({
1728
+ ...res,
1729
+ stage: res.stage
601
1730
  });
1731
+ } else {
1732
+ setResult(res);
602
1733
  }
603
- return {
604
- status: false,
605
- stage: "error",
606
- message: errorObj.message
607
- };
1734
+ return res;
1735
+ } catch (err) {
1736
+ const msg = err instanceof Error ? err.message : String(err);
1737
+ setError(msg);
1738
+ throw err;
608
1739
  } finally {
609
- if (isMounted.current) setLoading(false);
1740
+ await Promise.allSettled([refetchQuote(), refetchBalances()]);
1741
+ setLoading(false);
610
1742
  }
611
1743
  },
612
- []
1744
+ [sdk, refetchQuote, refetchBalances]
613
1745
  );
614
1746
  return {
615
- /** Executes the swap order. */
616
1747
  execute,
617
- /** Current execution stage. */
618
- status,
619
- /** Human-readable status message. */
1748
+ isLoading,
1749
+ stage,
620
1750
  message,
621
- /** Whether execution is ongoing. */
622
- loading,
623
- /** Raw SDK response data. */
624
- data,
625
- /** Captured error (if execution failed). */
626
- error
1751
+ error,
1752
+ result
627
1753
  };
628
1754
  }
629
1755
 
630
- // src/react/useQuote.ts
631
- var import_react3 = require("react");
632
-
633
- // src/core/getQuote.ts
634
- var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
635
- var import_viem4 = require("viem");
636
- async function getQuote(params) {
637
- if (!params.tokenIn?.address || !params.tokenOut?.address) {
638
- throw new Error("Both tokenIn and tokenOut must include an address.");
639
- }
640
- if (!params.sourceChainId || !params.destChainId) {
641
- throw new Error("Both sourceChainId and destChainId are required.");
642
- }
643
- if (params.amount <= 0n) {
644
- throw new Error("Amount must be greater than 0.");
645
- }
646
- const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
647
- const data = await import_intents_sdk8.QuoteProvider.getQuote({
648
- sourceChainId: params.sourceChainId,
649
- destChainId: params.destChainId,
650
- tokenIn: normalizedTokenIn,
651
- tokenOut: params.tokenOut.address,
652
- amount: params.amount
653
- });
654
- const inputSlippage = params.slippage ?? 5;
655
- const slippageDecimal = inputSlippage / 100;
656
- const slippage = Math.min(Math.max(slippageDecimal, 0), 0.5);
657
- let warning;
658
- if (slippage > 0.1) {
659
- warning = `\u26A0\uFE0F High slippage tolerance (${(slippage * 100).toFixed(2)}%) \u2014 price may vary significantly.`;
660
- }
661
- const estimatedAmountOut = BigInt(data.estimatedAmountOutReduced);
662
- const slippageBps = BigInt(Math.round(slippage * 1e4));
663
- const estimatedAmountOutAfterSlippage = estimatedAmountOut * (10000n - slippageBps) / 10000n;
664
- const pricePerInputToken = estimatedAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / BigInt(params.amount);
665
- return {
666
- amountOut: estimatedAmountOut,
667
- amountOutUsd: data.estimatedAmountOutUsd,
668
- amountInUsd: data.amountInUsd,
669
- minStablecoinsAmount: data.estimatedAmountInAsMinStablecoinAmount,
670
- tokenIn: {
671
- address: params.tokenIn.address,
672
- decimals: params.tokenIn.decimals ?? 18,
673
- chainId: params.sourceChainId
674
- },
675
- tokenOut: {
676
- address: params.tokenOut.address,
677
- decimals: params.tokenOut.decimals ?? 18,
678
- chainId: params.destChainId
679
- },
680
- amountIn: params.amount,
681
- pricePerInputToken,
682
- slippage,
683
- internal: {
684
- ...data,
685
- estimatedAmountOutReduced: estimatedAmountOutAfterSlippage
686
- },
687
- warning
688
- };
689
- }
690
-
691
- // src/react/useQuote.ts
692
- function useQuote(params, options) {
693
- const [data, setData] = (0, import_react3.useState)(null);
694
- const [loading, setLoading] = (0, import_react3.useState)(false);
695
- const [error, setError] = (0, import_react3.useState)(null);
696
- const [warning, setWarning] = (0, import_react3.useState)(null);
697
- const debounceMs = options?.debounceMs ?? 250;
698
- const autoRefreshMs = options?.autoRefreshMs;
699
- const abortRef = (0, import_react3.useRef)(null);
700
- const debounceRef = (0, import_react3.useRef)(null);
701
- const mounted = (0, import_react3.useRef)(false);
702
- (0, import_react3.useEffect)(() => {
703
- mounted.current = true;
704
- return () => {
705
- mounted.current = false;
706
- abortRef.current?.abort();
707
- if (debounceRef.current) clearTimeout(debounceRef.current);
708
- };
709
- }, []);
710
- const fetchQuote = (0, import_react3.useCallback)(
711
- async () => {
712
- if (!params) return;
1756
+ // src/react/useTokenList.ts
1757
+ var import_react5 = require("react");
1758
+ function useTokenList() {
1759
+ const [tokens, setTokens] = (0, import_react5.useState)([]);
1760
+ const [loading, setLoading] = (0, import_react5.useState)(false);
1761
+ const [error, setError] = (0, import_react5.useState)(null);
1762
+ const [hasMore, setHasMore] = (0, import_react5.useState)(true);
1763
+ const [page, setPage] = (0, import_react5.useState)(1);
1764
+ const sdk = useSwap();
1765
+ const pageRef = (0, import_react5.useRef)(1);
1766
+ const hasMoreRef = (0, import_react5.useRef)(true);
1767
+ const lastQuery = (0, import_react5.useRef)({});
1768
+ const cache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
1769
+ const isLoadingRef = (0, import_react5.useRef)(false);
1770
+ pageRef.current = page;
1771
+ hasMoreRef.current = hasMore;
1772
+ const loadTokens = (0, import_react5.useCallback)(
1773
+ async (params) => {
1774
+ const { q, networkId, reset } = params;
1775
+ if (isLoadingRef.current && !reset) return;
713
1776
  try {
1777
+ let currentPage = pageRef.current;
1778
+ if (reset) {
1779
+ currentPage = 1;
1780
+ setTokens([]);
1781
+ setPage(1);
1782
+ setHasMore(true);
1783
+ pageRef.current = 1;
1784
+ hasMoreRef.current = true;
1785
+ }
1786
+ if (!reset && !hasMoreRef.current) return;
1787
+ isLoadingRef.current = true;
714
1788
  setLoading(true);
715
- setWarning(null);
716
- const result = await getQuote(params);
717
- const serializeResult = serializeBigIntsToStrings(result);
718
- if (!mounted.current) return;
719
- setData((prev) => {
720
- if (JSON.stringify(prev) === JSON.stringify(serializeResult)) return prev;
721
- return serializeResult;
722
- });
723
- setWarning(result.warning ?? null);
724
1789
  setError(null);
725
- } catch (err) {
726
- if (err.name === "AbortError") return;
727
- console.error("[useQuote] fetch error:", err);
728
- if (mounted.current) setError(err instanceof Error ? err : new Error(String(err)));
1790
+ const cacheKey = JSON.stringify({
1791
+ q: q?.toLowerCase() ?? "",
1792
+ networkId: networkId ?? void 0,
1793
+ page: currentPage
1794
+ });
1795
+ if (cache.current.has(cacheKey)) {
1796
+ const cached = cache.current.get(cacheKey);
1797
+ setTokens((prev) => reset ? cached.results : [...prev, ...cached.results]);
1798
+ if (!reset && cached.results.length > 0) {
1799
+ const nextPage = currentPage + 1;
1800
+ setPage(nextPage);
1801
+ pageRef.current = nextPage;
1802
+ }
1803
+ isLoadingRef.current = false;
1804
+ setLoading(false);
1805
+ return;
1806
+ }
1807
+ const apiParams = {
1808
+ q,
1809
+ page: currentPage,
1810
+ limit: 20,
1811
+ ...networkId !== void 0 ? { networkId } : {}
1812
+ };
1813
+ const res = await sdk.getTokenList(apiParams);
1814
+ cache.current.set(cacheKey, res);
1815
+ setTokens((prev) => reset ? res.results : [...prev, ...res.results]);
1816
+ const isLastPage = res.results.length === 0 || res.results.length < 20 || res.count && currentPage * 20 >= res.count;
1817
+ setHasMore(!isLastPage);
1818
+ hasMoreRef.current = !isLastPage;
1819
+ if (!reset && !isLastPage) {
1820
+ const nextPage = currentPage + 1;
1821
+ setPage(nextPage);
1822
+ pageRef.current = nextPage;
1823
+ }
1824
+ lastQuery.current = { q, networkId };
1825
+ } catch (e) {
1826
+ console.error("useTokenList error:", e);
1827
+ setError("Failed to load tokens");
729
1828
  } finally {
730
- if (mounted.current) setLoading(false);
1829
+ setLoading(false);
1830
+ isLoadingRef.current = false;
731
1831
  }
732
1832
  },
733
- [params]
734
- );
735
- (0, import_react3.useEffect)(() => {
736
- if (!params) return;
737
- if (debounceRef.current) clearTimeout(debounceRef.current);
738
- debounceRef.current = setTimeout(() => {
739
- fetchQuote();
740
- }, debounceMs);
741
- return () => {
742
- if (debounceRef.current) clearTimeout(debounceRef.current);
743
- abortRef.current?.abort();
744
- };
745
- }, [params, debounceMs, fetchQuote]);
746
- (0, import_react3.useEffect)(() => {
747
- if (!autoRefreshMs || !params) return;
748
- const interval = setInterval(() => fetchQuote(), autoRefreshMs);
749
- return () => clearInterval(interval);
750
- }, [autoRefreshMs, params, fetchQuote]);
751
- return (0, import_react3.useMemo)(
752
- () => ({
753
- data,
754
- loading,
755
- error,
756
- warning,
757
- refetch: () => fetchQuote()
758
- }),
759
- [data, loading, error, warning, fetchQuote]
1833
+ [sdk]
760
1834
  );
761
- }
762
-
763
- // src/react/useBalances.ts
764
- var import_react4 = require("react");
765
-
766
- // src/core/getBalances.ts
767
- var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
768
- async function getBalances(params, options) {
769
- const { addresses, cursorEvm, cursorSvm } = params;
770
- const { signal } = options ?? {};
771
- if (!addresses?.evm && !addresses?.svm) {
772
- throw new Error("At least one address (EVM or SVM) must be provided.");
773
- }
774
- const payload = JSON.stringify({
775
- addresses,
776
- cursorEvm,
777
- cursorSvm
778
- });
779
- const start = performance.now();
780
- const response = await fetch(`${import_intents_sdk9.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
781
- method: "POST",
782
- headers: {
783
- accept: "application/json",
784
- "Content-Type": "application/json"
785
- },
786
- body: payload,
787
- signal
788
- }).catch((err) => {
789
- if (err.name === "AbortError") {
790
- throw new Error("Balance request was cancelled.");
791
- }
792
- throw err;
793
- });
794
- if (!response.ok) {
795
- const text = await response.text().catch(() => "");
796
- throw new Error(`Failed to fetch balances: ${response.status} ${text}`);
797
- }
798
- const data = await response.json().catch(() => {
799
- throw new Error("Invalid JSON response from balances API.");
800
- });
801
- const duration = (performance.now() - start).toFixed(1);
802
- if (process.env.NODE_ENV !== "production") {
803
- console.debug(`[Shogun SDK] Fetched balances in ${duration}ms`);
804
- }
805
- const evmItems = data.evm?.items ?? [];
806
- const svmItems = data.svm?.items ?? [];
807
- const combined = [...evmItems, ...svmItems];
1835
+ const resetTokens = (0, import_react5.useCallback)(() => {
1836
+ setTokens([]);
1837
+ setPage(1);
1838
+ setHasMore(true);
1839
+ pageRef.current = 1;
1840
+ hasMoreRef.current = true;
1841
+ cache.current.clear();
1842
+ lastQuery.current = {};
1843
+ }, []);
808
1844
  return {
809
- results: combined,
810
- nextCursorEvm: data.evm?.cursor ?? null,
811
- nextCursorSvm: data.svm?.cursor ?? null
1845
+ tokens,
1846
+ loading,
1847
+ error,
1848
+ hasMore,
1849
+ page,
1850
+ lastQuery: lastQuery.current,
1851
+ loadTokens,
1852
+ resetTokens
812
1853
  };
813
1854
  }
814
1855
 
815
- // src/react/useBalances.ts
816
- function useBalances(params) {
817
- const [data, setData] = (0, import_react4.useState)(null);
818
- const [loading, setLoading] = (0, import_react4.useState)(false);
819
- const [error, setError] = (0, import_react4.useState)(null);
820
- const abortRef = (0, import_react4.useRef)(null);
821
- const stableParams = (0, import_react4.useMemo)(() => {
822
- if (!params) return null;
823
- const { addresses, cursorEvm, cursorSvm } = params;
824
- return {
825
- addresses: {
826
- evm: addresses?.evm ?? void 0,
827
- svm: addresses?.svm ?? void 0
828
- },
829
- cursorEvm,
830
- cursorSvm
1856
+ // src/react/useTokensData.ts
1857
+ var import_react6 = require("react");
1858
+ function useTokensData(addresses) {
1859
+ const sdk = useSwap();
1860
+ const [data, setData] = (0, import_react6.useState)([]);
1861
+ const [loading, setLoading] = (0, import_react6.useState)(false);
1862
+ const [error, setError] = (0, import_react6.useState)(null);
1863
+ (0, import_react6.useEffect)(() => {
1864
+ if (!addresses?.length) return;
1865
+ let isMounted = true;
1866
+ setLoading(true);
1867
+ setError(null);
1868
+ sdk.getTokensData(addresses).then((res) => {
1869
+ if (isMounted) setData(res);
1870
+ }).catch((e) => {
1871
+ if (isMounted) setError(e instanceof Error ? e : new Error(String(e)));
1872
+ }).finally(() => {
1873
+ if (isMounted) setLoading(false);
1874
+ });
1875
+ return () => {
1876
+ isMounted = false;
831
1877
  };
832
- }, [params?.addresses?.evm, params?.addresses?.svm, params?.cursorEvm, params?.cursorSvm]);
833
- const fetchBalances = (0, import_react4.useCallback)(async () => {
834
- if (!stableParams) return;
1878
+ }, [sdk, JSON.stringify(addresses)]);
1879
+ return { data, loading, error };
1880
+ }
1881
+
1882
+ // src/react/useOrders.ts
1883
+ var import_react7 = require("react");
1884
+ var import_swr3 = __toESM(require("swr"), 1);
1885
+ var ORDERS_KEY = "orders-global";
1886
+ function hasValidAddress(addrs) {
1887
+ if (!addrs) return false;
1888
+ return Boolean(addrs.evmAddress || addrs.solAddress || addrs.suiAddress);
1889
+ }
1890
+ function useOrders(initialAddresses) {
1891
+ const sdk = useSwap();
1892
+ const abortRef = (0, import_react7.useRef)(null);
1893
+ const addrRef = globalThis.__ORDERS_ADDR_REF__ ?? (globalThis.__ORDERS_ADDR_REF__ = { current: initialAddresses ?? null });
1894
+ (0, import_react7.useEffect)(() => {
1895
+ if (initialAddresses && JSON.stringify(addrRef.current) !== JSON.stringify(initialAddresses)) {
1896
+ addrRef.current = initialAddresses;
1897
+ void (0, import_swr3.mutate)(ORDERS_KEY);
1898
+ }
1899
+ }, [initialAddresses]);
1900
+ const fetcher = (0, import_react7.useCallback)(async () => {
1901
+ const active = addrRef.current;
1902
+ if (!hasValidAddress(active)) return null;
835
1903
  if (abortRef.current) abortRef.current.abort();
836
1904
  const controller = new AbortController();
837
1905
  abortRef.current = controller;
838
- setLoading(true);
839
- setError(null);
840
1906
  try {
841
- const result = await getBalances(stableParams, { signal: controller.signal });
842
- setData((prev) => {
843
- if (JSON.stringify(prev) === JSON.stringify(result)) return prev;
844
- return result;
845
- });
846
- return result;
1907
+ return await sdk.getOrders(active ?? {});
847
1908
  } catch (err) {
848
- if (err.name === "AbortError") return;
849
- const e = err instanceof Error ? err : new Error(String(err));
850
- setError(e);
851
- throw e;
852
- } finally {
853
- setLoading(false);
1909
+ if (err instanceof DOMException && err.name === "AbortError") return null;
1910
+ if (err instanceof Error) throw err;
1911
+ throw new Error(String(err));
854
1912
  }
855
- }, [stableParams]);
856
- (0, import_react4.useEffect)(() => {
857
- if (stableParams) fetchBalances().catch(() => {
858
- });
859
- return () => {
860
- if (abortRef.current) abortRef.current.abort();
861
- };
862
- }, [fetchBalances]);
863
- return (0, import_react4.useMemo)(
1913
+ }, [sdk]);
1914
+ const {
1915
+ data,
1916
+ error,
1917
+ isValidating: loading,
1918
+ mutate: mutateOrders
1919
+ } = (0, import_swr3.default)(ORDERS_KEY, fetcher, {
1920
+ revalidateOnFocus: false,
1921
+ revalidateOnReconnect: false,
1922
+ shouldRetryOnError: false,
1923
+ keepPreviousData: true
1924
+ });
1925
+ const refetch = (0, import_react7.useCallback)(async () => {
1926
+ await mutateOrders();
1927
+ }, [mutateOrders]);
1928
+ const setAddresses = (0, import_react7.useCallback)(
1929
+ (next) => {
1930
+ if (!next) return;
1931
+ addrRef.current = next;
1932
+ void (0, import_swr3.mutate)(ORDERS_KEY);
1933
+ },
1934
+ []
1935
+ );
1936
+ return (0, import_react7.useMemo)(
864
1937
  () => ({
865
- /** Latest fetched balance data */
866
1938
  data,
867
- /** Whether the hook is currently fetching */
868
1939
  loading,
869
- /** Error object if fetching failed */
870
- error,
871
- /** Manually trigger a refresh */
872
- refetch: fetchBalances
1940
+ error: error instanceof Error ? error.message : null,
1941
+ refetch,
1942
+ setAddresses,
1943
+ get activeAddresses() {
1944
+ return addrRef.current;
1945
+ }
873
1946
  }),
874
- [data, loading, error, fetchBalances]
1947
+ [data, loading, error, refetch, setAddresses]
875
1948
  );
876
1949
  }
877
1950
 
878
- // src/react/index.ts
879
- var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
880
- // Annotate the CommonJS export names for ESM import in node:
881
- 0 && (module.exports = {
882
- ChainID,
883
- isEvmChain,
884
- useBalances,
885
- useExecuteOrder,
886
- useQuote,
887
- useTokenList
888
- });
1951
+ // src/react/useCancelOrder.ts
1952
+ var import_react8 = require("react");
1953
+ var import_swr4 = require("swr");
1954
+ function useCancelOrder() {
1955
+ const sdk = useSwap();
1956
+ const [isLoading, setLoading] = (0, import_react8.useState)(false);
1957
+ const [error, setError] = (0, import_react8.useState)(null);
1958
+ const [result, setResult] = (0, import_react8.useState)(null);
1959
+ const cancel = (0, import_react8.useCallback)(
1960
+ async (params) => {
1961
+ setLoading(true);
1962
+ setError(null);
1963
+ setResult(null);
1964
+ try {
1965
+ const tx = await sdk.cancelOrder({
1966
+ order: params.order,
1967
+ wallet: params.wallet,
1968
+ solRpc: params.solRpc
1969
+ });
1970
+ setResult(tx);
1971
+ void (0, import_swr4.mutate)("orders-global");
1972
+ return tx;
1973
+ } catch (err) {
1974
+ const msg = err instanceof Error ? err.message : String(err);
1975
+ setError(msg);
1976
+ throw err;
1977
+ } finally {
1978
+ setLoading(false);
1979
+ }
1980
+ },
1981
+ [sdk]
1982
+ );
1983
+ return {
1984
+ cancel,
1985
+ isLoading,
1986
+ error,
1987
+ result
1988
+ };
1989
+ }