@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/index.js CHANGED
@@ -1,15 +1,13 @@
1
- // src/core/token-list.ts
2
- import { getTokenList as intentsGetTokenList } from "@shogun-sdk/intents-sdk";
3
- async function getTokenList(params) {
4
- return intentsGetTokenList(params);
5
- }
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
4
 
7
5
  // src/core/getQuote.ts
8
6
  import { QuoteProvider } from "@shogun-sdk/intents-sdk";
9
7
  import { parseUnits } from "viem";
10
8
 
11
- // src/core/executeOrder/normalizeNative.ts
12
- import { isEvmChain } from "@shogun-sdk/intents-sdk";
9
+ // src/core/execute/normalizeNative.ts
10
+ import { isEvmChain as isEvmChain2 } from "@shogun-sdk/intents-sdk";
13
11
 
14
12
  // src/utils/address.ts
15
13
  import { zeroAddress } from "viem";
@@ -29,11 +27,25 @@ function normalizeEvmTokenAddress(address) {
29
27
  }
30
28
 
31
29
  // src/utils/chain.ts
32
- import { ChainID } from "@shogun-sdk/intents-sdk";
33
- var SOLANA_CHAIN_ID = ChainID.Solana;
34
- var SupportedChains = [
30
+ import { ChainID as BaseChainID, isEvmChain as isEvmChainIntent } from "@shogun-sdk/intents-sdk";
31
+ var SOLANA_CHAIN_ID = BaseChainID.Solana;
32
+ var CURRENT_SUPPORTED = [
33
+ BaseChainID.Solana,
34
+ BaseChainID.BSC,
35
+ BaseChainID.Base
36
+ ];
37
+ var ChainId = Object.entries(BaseChainID).reduce(
38
+ (acc, [key, value]) => {
39
+ if (typeof value === "number" && CURRENT_SUPPORTED.includes(value)) {
40
+ acc[key] = value;
41
+ }
42
+ return acc;
43
+ },
44
+ {}
45
+ );
46
+ var SupportedChainsInternal = [
35
47
  {
36
- id: ChainID.Arbitrum,
48
+ id: BaseChainID.Arbitrum,
37
49
  name: "Arbitrum",
38
50
  isEVM: true,
39
51
  wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -42,7 +54,7 @@ var SupportedChains = [
42
54
  tokenAddress: NATIVE_TOKEN.ETH
43
55
  },
44
56
  {
45
- id: ChainID.Optimism,
57
+ id: BaseChainID.Optimism,
46
58
  name: "Optimism",
47
59
  isEVM: true,
48
60
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -51,7 +63,7 @@ var SupportedChains = [
51
63
  tokenAddress: NATIVE_TOKEN.ETH
52
64
  },
53
65
  {
54
- id: ChainID.Base,
66
+ id: BaseChainID.Base,
55
67
  name: "Base",
56
68
  isEVM: true,
57
69
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -60,7 +72,7 @@ var SupportedChains = [
60
72
  tokenAddress: NATIVE_TOKEN.ETH
61
73
  },
62
74
  {
63
- id: ChainID.Hyperliquid,
75
+ id: BaseChainID.Hyperliquid,
64
76
  name: "Hyperliquid",
65
77
  isEVM: true,
66
78
  wrapped: "0x5555555555555555555555555555555555555555",
@@ -69,7 +81,7 @@ var SupportedChains = [
69
81
  tokenAddress: NATIVE_TOKEN.ETH
70
82
  },
71
83
  {
72
- id: ChainID.BSC,
84
+ id: BaseChainID.BSC,
73
85
  name: "BSC",
74
86
  isEVM: true,
75
87
  wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
@@ -87,6 +99,10 @@ var SupportedChains = [
87
99
  tokenAddress: NATIVE_TOKEN.SOL
88
100
  }
89
101
  ];
102
+ var SupportedChains = SupportedChainsInternal.filter(
103
+ (c) => CURRENT_SUPPORTED.includes(c.id)
104
+ );
105
+ var isEvmChain = isEvmChainIntent;
90
106
 
91
107
  // src/utils/viem.ts
92
108
  function isViemWalletClient(wallet) {
@@ -114,9 +130,9 @@ function serializeBigIntsToStrings(obj) {
114
130
  return obj;
115
131
  }
116
132
 
117
- // src/core/executeOrder/normalizeNative.ts
133
+ // src/core/execute/normalizeNative.ts
118
134
  function normalizeNative(chainId, address) {
119
- if (isEvmChain(chainId) && isNativeAddress(address)) {
135
+ if (isEvmChain2(chainId) && isNativeAddress(address)) {
120
136
  const chain = SupportedChains.find((c) => c.id === chainId);
121
137
  if (!chain?.wrapped)
122
138
  throw new Error(`Wrapped token not found for chainId ${chainId}`);
@@ -127,13 +143,14 @@ function normalizeNative(chainId, address) {
127
143
 
128
144
  // src/core/getQuote.ts
129
145
  async function getQuote(params) {
146
+ const amount = BigInt(params.amount);
130
147
  if (!params.tokenIn?.address || !params.tokenOut?.address) {
131
148
  throw new Error("Both tokenIn and tokenOut must include an address.");
132
149
  }
133
150
  if (!params.sourceChainId || !params.destChainId) {
134
151
  throw new Error("Both sourceChainId and destChainId are required.");
135
152
  }
136
- if (params.amount <= 0n) {
153
+ if (amount <= 0n) {
137
154
  throw new Error("Amount must be greater than 0.");
138
155
  }
139
156
  const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
@@ -142,7 +159,7 @@ async function getQuote(params) {
142
159
  destChainId: params.destChainId,
143
160
  tokenIn: normalizedTokenIn,
144
161
  tokenOut: params.tokenOut.address,
145
- amount: params.amount
162
+ amount
146
163
  });
147
164
  const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
148
165
  let warning;
@@ -173,7 +190,7 @@ async function getQuote(params) {
173
190
  decimals: params.tokenOut.decimals ?? 18,
174
191
  chainId: params.destChainId
175
192
  },
176
- amountIn: params.amount,
193
+ amountIn: BigInt(params.amount),
177
194
  pricePerInputToken,
178
195
  slippage: slippagePercent,
179
196
  internal: {
@@ -197,7 +214,7 @@ function buildQuoteParams({
197
214
  tokenOut,
198
215
  sourceChainId,
199
216
  destChainId,
200
- amount: parseUnits(amount.toString(), tokenIn.decimals ?? 18),
217
+ amount: parseUnits(amount.toString(), tokenIn.decimals ?? 18).toString(),
201
218
  slippage
202
219
  };
203
220
  }
@@ -244,59 +261,66 @@ async function getBalances(params, options) {
244
261
  const evmItems = data.evm?.items ?? [];
245
262
  const svmItems = data.svm?.items ?? [];
246
263
  const combined = [...evmItems, ...svmItems];
264
+ const filtered = combined.filter(
265
+ (b) => CURRENT_SUPPORTED.includes(b.chainId)
266
+ );
247
267
  return {
248
- results: combined,
268
+ results: filtered,
249
269
  nextCursorEvm: data.evm?.cursor ?? null,
250
270
  nextCursorSvm: data.svm?.cursor ?? null
251
271
  };
252
272
  }
253
273
 
254
- // src/core/executeOrder/execute.ts
255
- import { ChainID as ChainID3, isEvmChain as isEvmChain2 } from "@shogun-sdk/intents-sdk";
256
- import { BaseError } from "viem";
257
-
258
- // src/wallet-adapter/svm-wallet-adapter/adapter.ts
259
- import {
260
- Connection
261
- } from "@solana/web3.js";
262
- var adaptSolanaWallet = (walletAddress, chainId, rpcUrl, signAndSendTransaction) => {
263
- let _chainId = chainId;
264
- const connection = new Connection(rpcUrl, { commitment: "confirmed" });
265
- const getChainId = async () => _chainId;
266
- const sendTransaction = async (transaction) => {
267
- const txHash = await signAndSendTransaction(transaction);
268
- console.debug(`\u{1F6F0} Sent transaction: ${txHash}`);
269
- const maxRetries = 20;
270
- const delayMs = 2e3;
271
- for (let attempt = 0; attempt < maxRetries; attempt++) {
272
- const res = await connection.getSignatureStatus(txHash, { searchTransactionHistory: true });
273
- if (res?.value?.confirmationStatus === "confirmed" || res?.value?.confirmationStatus === "finalized") {
274
- return txHash;
275
- }
276
- await new Promise((resolve) => setTimeout(resolve, delayMs));
277
- }
278
- throw new Error(`Transaction not confirmed after ${maxRetries * (delayMs / 1e3)}s`);
279
- };
280
- const signTypedData = async () => {
281
- throw new Error("signTypedData not implemented for Solana");
282
- };
283
- const switchChain = async (newChainId) => {
284
- _chainId = newChainId;
285
- };
274
+ // src/core/token-list.ts
275
+ import { TOKEN_SEARCH_API_BASE_URL as TOKEN_SEARCH_API_BASE_URL2 } from "@shogun-sdk/intents-sdk";
276
+ async function getTokenList(params) {
277
+ const url = new URL(`${TOKEN_SEARCH_API_BASE_URL2}/tokens/search`);
278
+ if (params.q) url.searchParams.append("q", params.q);
279
+ if (params.networkId) url.searchParams.append("networkId", String(params.networkId));
280
+ if (params.page) url.searchParams.append("page", String(params.page));
281
+ if (params.limit) url.searchParams.append("limit", String(params.limit));
282
+ const res = await fetch(url.toString(), {
283
+ signal: params.signal
284
+ });
285
+ if (!res.ok) {
286
+ throw new Error(`Failed to fetch tokens: ${res.status} ${res.statusText}`);
287
+ }
288
+ const data = await res.json();
289
+ const filteredResults = data.results.filter(
290
+ (token) => CURRENT_SUPPORTED.includes(token.chainId)
291
+ );
286
292
  return {
287
- vmType: "SVM" /* SVM */,
288
- getChainId,
289
- address: async () => walletAddress,
290
- sendTransaction,
291
- switchChain,
292
- signTypedData,
293
- rpcUrl
293
+ ...data,
294
+ results: filteredResults,
295
+ count: filteredResults.length
294
296
  };
295
- };
297
+ }
298
+
299
+ // src/core/token.ts
300
+ import { TOKEN_SEARCH_API_BASE_URL as TOKEN_SEARCH_API_BASE_URL3 } from "@shogun-sdk/intents-sdk";
301
+ async function getTokensData(addresses) {
302
+ if (!addresses?.length) return [];
303
+ const response = await fetch(`${TOKEN_SEARCH_API_BASE_URL3}/tokens/tokens`, {
304
+ method: "POST",
305
+ headers: {
306
+ "Content-Type": "application/json",
307
+ accept: "*/*"
308
+ },
309
+ body: JSON.stringify({ addresses })
310
+ });
311
+ if (!response.ok) {
312
+ throw new Error(`Failed to fetch token data: ${response.statusText}`);
313
+ }
314
+ const data = await response.json();
315
+ const filtered = data.filter((t) => CURRENT_SUPPORTED.includes(Number(t.chainId)));
316
+ return filtered;
317
+ }
318
+
319
+ // src/core/execute/execute.ts
320
+ import { ChainID as ChainID2, isEvmChain as isEvmChain3 } from "@shogun-sdk/intents-sdk";
321
+ import "viem";
296
322
 
297
323
  // src/wallet-adapter/evm-wallet-adapter/adapter.ts
298
- import { utils as ethersUtils } from "ethers/lib/ethers.js";
299
- import { hexValue } from "ethers/lib/utils.js";
300
324
  import {
301
325
  custom,
302
326
  publicActions
@@ -304,64 +328,6 @@ import {
304
328
  function isEVMTransaction(tx) {
305
329
  return typeof tx.from === "string";
306
330
  }
307
- var adaptEthersSigner = (signer, transport) => {
308
- const signTypedData = async (signData) => {
309
- const typedSigner = signer;
310
- return await typedSigner._signTypedData(
311
- signData.domain,
312
- signData.types,
313
- signData.value
314
- );
315
- };
316
- const sendTransaction = async (transaction) => {
317
- if (!isEVMTransaction(transaction)) {
318
- throw new Error("Expected EVMTransaction but got SolanaTransaction");
319
- }
320
- const tx = await signer.sendTransaction({
321
- from: transaction.from,
322
- to: transaction.to,
323
- data: transaction.data,
324
- value: transaction.value
325
- });
326
- return tx.hash;
327
- };
328
- const switchChain = async (chainId) => {
329
- try {
330
- await window.ethereum.request({
331
- method: "wallet_switchEthereumChain",
332
- params: [{ chainId: hexValue(chainId) }]
333
- });
334
- } catch (error) {
335
- console.error("Failed to switch chain:", error);
336
- throw error;
337
- }
338
- };
339
- const readContract = async ({
340
- address,
341
- abi,
342
- functionName,
343
- args = []
344
- }) => {
345
- const iface = new ethersUtils.Interface(abi);
346
- const fnArgs = Array.isArray(args) ? args : [];
347
- const data = iface.encodeFunctionData(functionName, fnArgs);
348
- const provider = signer.provider;
349
- if (!provider) throw new Error("Signer has no provider");
350
- const result = await provider.call({ to: address, data });
351
- const decoded = iface.decodeFunctionResult(functionName, result);
352
- return decoded[0];
353
- };
354
- return {
355
- vmType: "EVM" /* EVM */,
356
- transport,
357
- getChainId: async () => signer.getChainId(),
358
- address: async () => signer.getAddress(),
359
- sendTransaction,
360
- signTypedData,
361
- switchChain,
362
- readContract
363
- };
364
- };
365
331
  var adaptViemWallet = (wallet) => {
366
332
  const signTypedData = async (signData) => {
367
333
  return await wallet.signTypedData({
@@ -444,14 +410,14 @@ var adaptViemWallet = (wallet) => {
444
410
  };
445
411
  };
446
412
 
447
- // src/core/executeOrder/handleEvmExecution.ts
413
+ // src/core/execute/handleEvmExecution.ts
448
414
  import {
449
415
  getEVMSingleChainOrderTypedData,
450
416
  getEVMCrossChainOrderTypedData
451
417
  } from "@shogun-sdk/intents-sdk";
452
418
  import { encodeFunctionData as encodeFunctionData2 } from "viem";
453
419
 
454
- // src/core/executeOrder/stageMessages.ts
420
+ // src/core/execute/stageMessages.ts
455
421
  var DEFAULT_STAGE_MESSAGES = {
456
422
  processing: "Preparing transaction for execution",
457
423
  approving: "Approving token allowance",
@@ -460,20 +426,44 @@ var DEFAULT_STAGE_MESSAGES = {
460
426
  submitting: "Submitting transaction",
461
427
  initiated: "Transaction initiated.",
462
428
  success: "Transaction Executed successfully",
429
+ success_limit: "Limit order has been submitted successfully.",
463
430
  shogun_processing: "Shogun is processing your transaction",
464
431
  error: "Transaction failed during submission"
465
432
  };
466
433
 
467
- // src/core/executeOrder/buildOrder.ts
434
+ // src/core/execute/buildOrder.ts
468
435
  import { CrossChainOrder, SingleChainOrder } from "@shogun-sdk/intents-sdk";
436
+ import { formatUnits, parseUnits as parseUnits2 } from "viem";
437
+
438
+ // src/utils/order.ts
439
+ var OrderExecutionType = /* @__PURE__ */ ((OrderExecutionType2) => {
440
+ OrderExecutionType2["LIMIT"] = "limit";
441
+ OrderExecutionType2["MARKET"] = "market";
442
+ return OrderExecutionType2;
443
+ })(OrderExecutionType || {});
444
+
445
+ // src/core/execute/buildOrder.ts
469
446
  async function buildOrder({
470
447
  quote,
471
448
  accountAddress,
472
449
  destination,
473
450
  deadline,
474
- isSingleChain
451
+ isSingleChain,
452
+ orderType,
453
+ options
475
454
  }) {
476
455
  const { tokenIn, tokenOut } = quote;
456
+ let amountOutMin = BigInt(quote.internal.estimatedAmountOutReduced);
457
+ if (orderType === "limit" /* LIMIT */ && options && "executionPrice" in options) {
458
+ const executionPrice = Number(options.executionPrice);
459
+ if (Number.isFinite(executionPrice) && executionPrice > 0) {
460
+ const decimalsIn = tokenIn.decimals ?? 18;
461
+ const decimalsOut = tokenOut.decimals ?? 18;
462
+ const formattedAmountIn = Number(formatUnits(BigInt(quote.amountIn.toString()), decimalsIn));
463
+ const rawAmountOut = formattedAmountIn * executionPrice;
464
+ amountOutMin = parseUnits2(rawAmountOut.toString(), decimalsOut);
465
+ }
466
+ }
477
467
  if (isSingleChain) {
478
468
  return await SingleChainOrder.create({
479
469
  user: accountAddress,
@@ -481,7 +471,7 @@ async function buildOrder({
481
471
  tokenIn: tokenIn.address,
482
472
  tokenOut: tokenOut.address,
483
473
  amountIn: quote.amountIn,
484
- amountOutMin: quote.internal.estimatedAmountOutReduced,
474
+ amountOutMin,
485
475
  deadline,
486
476
  destinationAddress: destination
487
477
  });
@@ -495,7 +485,7 @@ async function buildOrder({
495
485
  destinationTokenAddress: tokenOut.address,
496
486
  destinationAddress: destination,
497
487
  deadline,
498
- destinationTokenMinAmount: quote.internal.estimatedAmountOutReduced,
488
+ destinationTokenMinAmount: amountOutMin,
499
489
  minStablecoinAmount: quote.minStablecoinsAmount
500
490
  });
501
491
  }
@@ -566,7 +556,7 @@ async function pollOrderStatus(address, orderId, options = {}) {
566
556
  });
567
557
  }
568
558
 
569
- // src/core/executeOrder/handleOrderPollingResult.ts
559
+ // src/core/execute/handleOrderPollingResult.ts
570
560
  async function handleOrderPollingResult({
571
561
  status,
572
562
  orderId,
@@ -604,7 +594,7 @@ async function handleOrderPollingResult({
604
594
  };
605
595
  }
606
596
 
607
- // src/core/executeOrder/ensurePermit2Allowance.ts
597
+ // src/core/execute/ensurePermit2Allowance.ts
608
598
  import { encodeFunctionData, erc20Abi, maxUint256 } from "viem";
609
599
  import { PERMIT2_ADDRESS } from "@shogun-sdk/intents-sdk";
610
600
  async function ensurePermit2Allowance({
@@ -649,7 +639,7 @@ async function ensurePermit2Allowance({
649
639
  );
650
640
  }
651
641
 
652
- // src/core/executeOrder/handleEvmExecution.ts
642
+ // src/core/execute/handleEvmExecution.ts
653
643
  async function handleEvmExecution({
654
644
  recipientAddress,
655
645
  quote,
@@ -657,16 +647,19 @@ async function handleEvmExecution({
657
647
  accountAddress,
658
648
  wallet,
659
649
  isSingleChain,
660
- deadline,
661
- update
650
+ update,
651
+ orderType,
652
+ options
662
653
  }) {
663
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
654
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
655
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
664
656
  await wallet.switchChain(chainId);
665
657
  const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
666
658
  quote.tokenOut.address = normalizeEvmTokenAddress(quote.tokenOut.address);
667
659
  const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
668
660
  update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
669
661
  if (shouldWrapNative) {
662
+ quote.tokenIn.address === tokenIn;
670
663
  await wallet.sendTransaction({
671
664
  to: tokenIn,
672
665
  data: encodeFunctionData2({
@@ -693,7 +686,9 @@ async function handleEvmExecution({
693
686
  accountAddress,
694
687
  destination,
695
688
  deadline,
696
- isSingleChain
689
+ isSingleChain,
690
+ orderType,
691
+ options
697
692
  });
698
693
  console.debug(`order`, order);
699
694
  update("processing", messageFor("signing"));
@@ -717,22 +712,33 @@ async function handleEvmExecution({
717
712
  update("initiated", messageFor("initiated"));
718
713
  const { intentId: orderId } = res.data;
719
714
  update("initiated", messageFor("shogun_processing"));
720
- const status = await pollOrderStatus(accountAddress, orderId);
721
- return await handleOrderPollingResult({
722
- status,
723
- orderId,
724
- chainId,
725
- update,
726
- messageFor
727
- });
715
+ if (orderType === "limit" /* LIMIT */) {
716
+ update("success", messageFor("success_limit"));
717
+ return {
718
+ status: true,
719
+ orderId,
720
+ chainId,
721
+ finalStatus: "OrderPlaced",
722
+ stage: "success"
723
+ };
724
+ } else {
725
+ const status = await pollOrderStatus(accountAddress, orderId);
726
+ return await handleOrderPollingResult({
727
+ status,
728
+ orderId,
729
+ chainId,
730
+ update,
731
+ messageFor
732
+ });
733
+ }
728
734
  }
729
735
 
730
- // src/core/executeOrder/handleSolanaExecution.ts
736
+ // src/core/execute/handleSolanaExecution.ts
731
737
  import {
732
738
  getSolanaSingleChainOrderInstructions,
733
739
  getSolanaCrossChainOrderInstructions
734
740
  } from "@shogun-sdk/intents-sdk";
735
- import { VersionedTransaction as VersionedTransaction2 } from "@solana/web3.js";
741
+ import { VersionedTransaction } from "@solana/web3.js";
736
742
  async function handleSolanaExecution({
737
743
  recipientAddress,
738
744
  quote,
@@ -740,12 +746,14 @@ async function handleSolanaExecution({
740
746
  isSingleChain,
741
747
  update,
742
748
  accountAddress,
743
- deadline
749
+ orderType,
750
+ options
744
751
  }) {
745
752
  if (!wallet.rpcUrl) {
746
753
  throw new Error("Solana wallet is missing rpcUrl");
747
754
  }
748
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
755
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
756
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
749
757
  update("processing", messageFor("processing"));
750
758
  const destination = recipientAddress ?? accountAddress;
751
759
  const order = await buildOrder({
@@ -753,14 +761,16 @@ async function handleSolanaExecution({
753
761
  accountAddress,
754
762
  destination,
755
763
  deadline,
756
- isSingleChain
764
+ isSingleChain,
765
+ orderType,
766
+ options
757
767
  });
758
768
  const txData = await getSolanaOrderInstructions({
759
769
  order,
760
770
  isSingleChain,
761
771
  rpcUrl: wallet.rpcUrl
762
772
  });
763
- const transaction = VersionedTransaction2.deserialize(Uint8Array.from(txData.txBytes));
773
+ const transaction = VersionedTransaction.deserialize(Uint8Array.from(txData.txBytes));
764
774
  update("processing", messageFor("signing"));
765
775
  await wallet.sendTransaction(transaction);
766
776
  update("processing", messageFor("submitting"));
@@ -773,16 +783,27 @@ async function handleSolanaExecution({
773
783
  throw new Error("Auctioneer submission failed");
774
784
  }
775
785
  update("initiated", messageFor("initiated"));
776
- const { jwt, intentId: orderId } = response.data;
786
+ const { intentId: orderId } = response.data;
777
787
  update("initiated", messageFor("shogun_processing"));
778
- const status = await pollOrderStatus(jwt, orderId);
779
- return await handleOrderPollingResult({
780
- status,
781
- orderId,
782
- chainId: SOLANA_CHAIN_ID,
783
- update,
784
- messageFor
785
- });
788
+ if (orderType === "limit" /* LIMIT */) {
789
+ update("success", messageFor("success_limit"));
790
+ return {
791
+ status: true,
792
+ orderId,
793
+ chainId: SOLANA_CHAIN_ID,
794
+ finalStatus: "OrderPlaced",
795
+ stage: "success"
796
+ };
797
+ } else {
798
+ const status = await pollOrderStatus(accountAddress, orderId);
799
+ return await handleOrderPollingResult({
800
+ status,
801
+ orderId,
802
+ chainId: SOLANA_CHAIN_ID,
803
+ update,
804
+ messageFor
805
+ });
806
+ }
786
807
  }
787
808
  async function getSolanaOrderInstructions({
788
809
  order,
@@ -815,13 +836,14 @@ async function submitToAuctioneer({
815
836
  });
816
837
  }
817
838
 
818
- // src/core/executeOrder/execute.ts
839
+ // src/core/execute/execute.ts
819
840
  async function executeOrder({
820
841
  quote,
821
842
  accountAddress,
822
843
  recipientAddress,
823
844
  wallet,
824
845
  onStatus,
846
+ orderType = "market" /* MARKET */,
825
847
  options = {}
826
848
  }) {
827
849
  const isDev = process.env.NODE_ENV !== "production";
@@ -834,21 +856,31 @@ async function executeOrder({
834
856
  onStatus?.(stage, message ?? messageFor(stage));
835
857
  };
836
858
  try {
837
- const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
838
859
  log("Starting execution:", {
839
860
  accountAddress,
840
861
  recipientAddress,
841
- deadline,
842
862
  tokenIn: quote?.tokenIn,
843
863
  tokenOut: quote?.tokenOut
844
864
  });
845
865
  const adapter = normalizeWallet(wallet);
846
866
  if (!adapter) throw new Error("No wallet provided");
847
867
  const { tokenIn, tokenOut } = quote;
868
+ const srcChain = Number(tokenIn.chainId);
869
+ const destChain = Number(tokenOut.chainId);
870
+ if (!CURRENT_SUPPORTED.includes(srcChain) || !CURRENT_SUPPORTED.includes(destChain)) {
871
+ const unsupportedChains = [
872
+ !CURRENT_SUPPORTED.includes(srcChain) ? srcChain : null,
873
+ !CURRENT_SUPPORTED.includes(destChain) ? destChain : null
874
+ ].filter(Boolean).join(", ");
875
+ const errorMsg = `Unsupported chain(s): ${unsupportedChains}`;
876
+ update("error", errorMsg);
877
+ log("Error:", errorMsg);
878
+ throw new Error(errorMsg);
879
+ }
848
880
  const isSingleChain = tokenIn.chainId === tokenOut.chainId;
849
881
  const chainId = Number(tokenIn.chainId);
850
882
  update("processing");
851
- if (isEvmChain2(chainId)) {
883
+ if (isEvmChain3(chainId)) {
852
884
  log("Detected EVM chain:", chainId);
853
885
  const result = await handleEvmExecution({
854
886
  recipientAddress,
@@ -857,13 +889,14 @@ async function executeOrder({
857
889
  accountAddress,
858
890
  wallet: adapter,
859
891
  isSingleChain,
860
- deadline,
861
- update
892
+ update,
893
+ orderType,
894
+ options
862
895
  });
863
896
  log("EVM execution result:", result);
864
897
  return result;
865
898
  }
866
- if (chainId === ChainID3.Solana) {
899
+ if (chainId === ChainID2.Solana) {
867
900
  log("Detected Solana chain");
868
901
  const result = await handleSolanaExecution({
869
902
  recipientAddress,
@@ -871,8 +904,9 @@ async function executeOrder({
871
904
  accountAddress,
872
905
  wallet: adapter,
873
906
  isSingleChain,
874
- deadline,
875
- update
907
+ update,
908
+ orderType,
909
+ options
876
910
  });
877
911
  log("Solana execution result:", result);
878
912
  return result;
@@ -882,8 +916,13 @@ async function executeOrder({
882
916
  log("Error:", unsupported);
883
917
  return { status: false, message: unsupported, stage: "error" };
884
918
  } catch (error) {
885
- const message = error instanceof BaseError ? error.shortMessage : error instanceof Error ? error.message : String(error);
886
- log("Execution failed:", { message, error });
919
+ let message = "An unknown error occurred";
920
+ if (error && typeof error === "object") {
921
+ const err = error;
922
+ message = err.details ?? err.message ?? message;
923
+ } else if (typeof error === "string") {
924
+ message = error;
925
+ }
887
926
  update("error", message);
888
927
  return { status: false, message, stage: "error" };
889
928
  }
@@ -894,320 +933,185 @@ function normalizeWallet(wallet) {
894
933
  return wallet;
895
934
  }
896
935
 
897
- // src/react/useTokenList.ts
898
- import { useEffect, useMemo, useRef, useState } from "react";
899
- var tokenCache = /* @__PURE__ */ new Map();
900
- function useTokenList(params) {
901
- const [data, setData] = useState(null);
902
- const [loading, setLoading] = useState(false);
903
- const [error, setError] = useState(null);
904
- const controllerRef = useRef(null);
905
- const debounceRef = useRef(null);
906
- const debounceMs = params.debounceMs ?? 250;
907
- const cacheKey = useMemo(() => {
908
- return JSON.stringify({
909
- q: params.q?.trim().toLowerCase() ?? "",
910
- networkId: params.networkId ?? "all",
911
- page: params.page ?? 1,
912
- limit: params.limit ?? 50
913
- });
914
- }, [params.q, params.networkId, params.page, params.limit]);
915
- async function fetchTokens(signal) {
916
- if (tokenCache.has(cacheKey)) {
917
- setData(tokenCache.get(cacheKey));
918
- setLoading(false);
919
- setError(null);
920
- return;
921
- }
922
- try {
923
- setLoading(true);
924
- const result = await getTokenList({ ...params, signal });
925
- tokenCache.set(cacheKey, result);
926
- setData(result);
927
- setError(null);
928
- } catch (err) {
929
- if (err.name !== "AbortError") {
930
- const e = err instanceof Error ? err : new Error("Unknown error while fetching tokens");
931
- setError(e);
932
- }
933
- } finally {
934
- setLoading(false);
935
- }
936
+ // src/core/orders/getOrders.ts
937
+ import { fetchUserOrders } from "@shogun-sdk/intents-sdk";
938
+ async function getOrders({
939
+ evmAddress,
940
+ solAddress
941
+ }) {
942
+ if (!evmAddress && !solAddress) {
943
+ throw new Error("At least one wallet address (EVM, Solana) must be provided.");
936
944
  }
937
- useEffect(() => {
938
- if (!params.q && !params.networkId) return;
939
- if (debounceRef.current) clearTimeout(debounceRef.current);
940
- if (controllerRef.current) controllerRef.current.abort();
941
- const controller = new AbortController();
942
- controllerRef.current = controller;
943
- debounceRef.current = setTimeout(() => {
944
- fetchTokens(controller.signal);
945
- }, debounceMs);
946
- return () => {
947
- controller.abort();
948
- if (debounceRef.current) clearTimeout(debounceRef.current);
949
- };
950
- }, [cacheKey, debounceMs]);
951
- return useMemo(
952
- () => ({
953
- /** Current fetched data (cached when possible) */
954
- data,
955
- /** Whether a request is in progress */
956
- loading,
957
- /** Error object if a request failed */
958
- error,
959
- /** Manually refetch the token list */
960
- refetch: () => fetchTokens(),
961
- /** Clear all cached token results (shared across hook instances) */
962
- clearCache: () => tokenCache.clear()
963
- }),
964
- [data, loading, error]
965
- );
945
+ const orders = await fetchUserOrders(evmAddress, solAddress);
946
+ return orders;
966
947
  }
967
948
 
968
- // src/react/useExecuteOrder.ts
969
- import { useState as useState2, useCallback, useRef as useRef2, useEffect as useEffect2 } from "react";
970
- function useExecuteOrder() {
971
- const [status, setStatus] = useState2("processing");
972
- const [message, setMessage] = useState2(null);
973
- const [loading, setLoading] = useState2(false);
974
- const [data, setData] = useState2(null);
975
- const [error, setError] = useState2(null);
976
- const isMounted = useRef2(true);
977
- useEffect2(() => {
978
- return () => {
979
- isMounted.current = false;
980
- };
981
- }, []);
982
- const execute = useCallback(
983
- async ({
949
+ // src/core/client.ts
950
+ var SwapSDK = class {
951
+ constructor(config) {
952
+ __publicField(this, "apiKey");
953
+ /**
954
+ * Fetches metadata for one or more tokens from the Shogun Token Search API.
955
+ *
956
+ * ---
957
+ * ### Overview
958
+ * `getTokensData` retrieves normalized token information — such as symbol, name,
959
+ * decimals, logo URI, and verified status — for a given list of token addresses.
960
+ *
961
+ * It supports both **EVM** and **SVM (Solana)** tokens, returning metadata from
962
+ * Shogun’s unified token registry.
963
+ *
964
+ * ---
965
+ * @example
966
+ * ```ts
967
+ * const tokens = await getTokensData([
968
+ * "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
969
+ * "So11111111111111111111111111111111111111112", // SOL
970
+ * ]);
971
+ *
972
+ * console.log(tokens);
973
+ * [
974
+ * { symbol: "USDC", name: "USD Coin", chainId: 1, decimals: 6, ... },
975
+ * { symbol: "SOL", name: "Solana", chainId: 101, decimals: 9, ... }
976
+ * ]
977
+ * ```
978
+ *
979
+ * @param addresses - An array of token addresses (EVM or SVM) to fetch metadata for.
980
+ * @returns A promise resolving to an array of {@link TokenInfo} objects.
981
+ *
982
+ * @throws Will throw an error if the network request fails or the API responds with a non-OK status.
983
+ */
984
+ __publicField(this, "getTokensData", getTokensData.bind(this));
985
+ if (!config.apiKey) {
986
+ throw new Error("SwapSDK: Missing API key");
987
+ }
988
+ this.apiKey = config.apiKey;
989
+ if (this.apiKey) void this.apiKey;
990
+ }
991
+ /**
992
+ * Retrieves a swap quote for the given input and output tokens.
993
+ *
994
+ * @param params - Quote parameters including source/destination tokens and amount.
995
+ * @returns A normalized `SwapQuoteResponse` containing output amount, route, and metadata.
996
+ */
997
+ async getQuote(params) {
998
+ return getQuote(params);
999
+ }
1000
+ /**
1001
+ * Fetches token balances for the specified user wallet(s).
1002
+ *
1003
+ * Supports both EVM and SVM (Solana) wallet addresses.
1004
+ *
1005
+ * @param params - Wallet address and optional chain filters.
1006
+ * @param options - Optional abort signal for cancellation.
1007
+ * @returns A unified balance response with per-chain token details.
1008
+ */
1009
+ async getBalances(params, options) {
1010
+ return getBalances(params, options);
1011
+ }
1012
+ /**
1013
+ * Retrieves a list of verified tokens based on search query or chain filter.
1014
+ *
1015
+ * @param params - Search parameters (query, chain ID, pagination options).
1016
+ * @returns Paginated `TokenSearchResponse` containing token metadata.
1017
+ */
1018
+ async getTokenList(params) {
1019
+ return getTokenList(params);
1020
+ }
1021
+ /**
1022
+ * Executes a prepared swap quote using the provided wallet and configuration.
1023
+ *
1024
+ * Handles:
1025
+ * - Token approval (if required)
1026
+ * - Transaction signing and broadcasting
1027
+ * - Confirmation polling and stage-based status updates
1028
+ *
1029
+ * Supports both:
1030
+ * - Market orders (with optional deadline)
1031
+ * - Limit orders (requires executionPrice and deadline)
1032
+ *
1033
+ * @param quote - The swap quote to execute, containing route and metadata.
1034
+ * @param accountAddress - The user's wallet address executing the swap.
1035
+ * @param recipientAddress - Optional recipient address for the output tokens (defaults to sender).
1036
+ * @param wallet - Adapted wallet instance (EVM/Solana) or a standard Viem `WalletClient`.
1037
+ * @param onStatus - Optional callback for receiving execution stage updates and messages.
1038
+ * @param orderType - Defines whether this is a market or limit order.
1039
+ * @param options - Execution parameters (different per order type).
1040
+ *
1041
+ * @returns A finalized execution result containing transaction hash, status, and any returned data.
1042
+ *
1043
+ * @example
1044
+ * ```ts
1045
+ * * Market order
1046
+ * const result = await sdk.executeTransaction({
1047
+ * quote,
1048
+ * accountAddress: "0x123...",
1049
+ * wallet,
1050
+ * orderType: OrderExecutionType.MARKET,
1051
+ * options: { deadline: 1800 },
1052
+ * onStatus: (stage, msg) => console.log(stage, msg),
1053
+ * });
1054
+ *
1055
+ * * Limit order
1056
+ * const result = await sdk.executeTransaction({
1057
+ * quote,
1058
+ * accountAddress: "0x123...",
1059
+ * wallet,
1060
+ * orderType: OrderExecutionType.LIMIT,
1061
+ * options: { executionPrice: "0.0021", deadline: 3600 },
1062
+ * });
1063
+ * ```
1064
+ */
1065
+ async executeTransaction({
1066
+ quote,
1067
+ accountAddress,
1068
+ recipientAddress,
1069
+ wallet,
1070
+ onStatus,
1071
+ orderType,
1072
+ options
1073
+ }) {
1074
+ return executeOrder({
984
1075
  quote,
1076
+ wallet,
985
1077
  accountAddress,
986
1078
  recipientAddress,
987
- wallet,
988
- deadline
989
- }) => {
990
- if (!quote || !wallet) {
991
- throw new Error("Quote and wallet are required for order execution.");
992
- }
993
- setLoading(true);
994
- setError(null);
995
- setData(null);
996
- setMessage(null);
997
- try {
998
- const effectiveDeadline = deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
999
- const onStatus = (stage, msg) => {
1000
- if (!isMounted.current) return;
1001
- setStatus(stage);
1002
- if (msg) setMessage(msg);
1003
- };
1004
- const result = await executeOrder({
1005
- quote,
1006
- accountAddress,
1007
- recipientAddress,
1008
- wallet,
1009
- onStatus,
1010
- options: { deadline: effectiveDeadline }
1011
- });
1012
- if (!isMounted.current) return result;
1013
- setData(result);
1014
- setStatus(result.stage);
1015
- setMessage("Order executed successfully");
1016
- return result;
1017
- } catch (err) {
1018
- const errorObj = err instanceof Error ? err : new Error(String(err));
1019
- if (isMounted.current) {
1020
- setError(errorObj);
1021
- setStatus("error");
1022
- setMessage(errorObj.message);
1023
- setData({
1024
- status: false,
1025
- stage: "error",
1026
- message: errorObj.message
1027
- });
1028
- }
1029
- return {
1030
- status: false,
1031
- stage: "error",
1032
- message: errorObj.message
1033
- };
1034
- } finally {
1035
- if (isMounted.current) setLoading(false);
1036
- }
1037
- },
1038
- []
1039
- );
1040
- return {
1041
- /** Executes the swap order. */
1042
- execute,
1043
- /** Current execution stage. */
1044
- status,
1045
- /** Human-readable status message. */
1046
- message,
1047
- /** Whether execution is ongoing. */
1048
- loading,
1049
- /** Raw SDK response data. */
1050
- data,
1051
- /** Captured error (if execution failed). */
1052
- error
1053
- };
1054
- }
1055
-
1056
- // src/react/useQuote.ts
1057
- import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
1058
- function useQuote(params, options) {
1059
- const [data, setData] = useState3(null);
1060
- const [loading, setLoading] = useState3(false);
1061
- const [error, setError] = useState3(null);
1062
- const [warning, setWarning] = useState3(null);
1063
- const debounceMs = options?.debounceMs ?? 250;
1064
- const autoRefreshMs = options?.autoRefreshMs;
1065
- const abortRef = useRef3(null);
1066
- const debounceRef = useRef3(null);
1067
- const mounted = useRef3(false);
1068
- const paramsKey = useMemo2(
1069
- () => params ? JSON.stringify(serializeBigIntsToStrings(params)) : null,
1070
- [params]
1071
- );
1072
- useEffect3(() => {
1073
- mounted.current = true;
1074
- return () => {
1075
- mounted.current = false;
1076
- abortRef.current?.abort();
1077
- if (debounceRef.current) clearTimeout(debounceRef.current);
1078
- };
1079
- }, []);
1080
- const fetchQuote = useCallback2(async () => {
1081
- if (!params) return;
1082
- try {
1083
- setLoading(true);
1084
- setWarning(null);
1085
- const result = await getQuote(params);
1086
- const serializeResult = serializeBigIntsToStrings(result);
1087
- if (!mounted.current) return;
1088
- setData((prev) => {
1089
- if (JSON.stringify(prev) === JSON.stringify(serializeResult)) return prev;
1090
- return serializeResult;
1091
- });
1092
- setWarning(result.warning ?? null);
1093
- setError(null);
1094
- } catch (err) {
1095
- if (err.name === "AbortError") return;
1096
- console.error("[useQuote] fetch error:", err);
1097
- if (mounted.current) setError(err instanceof Error ? err : new Error(String(err)));
1098
- } finally {
1099
- if (mounted.current) setLoading(false);
1100
- }
1101
- }, [paramsKey]);
1102
- useEffect3(() => {
1103
- if (!paramsKey) return;
1104
- if (debounceRef.current) clearTimeout(debounceRef.current);
1105
- debounceRef.current = setTimeout(() => {
1106
- fetchQuote();
1107
- }, debounceMs);
1108
- return () => {
1109
- if (debounceRef.current) clearTimeout(debounceRef.current);
1110
- abortRef.current?.abort();
1111
- };
1112
- }, [paramsKey, debounceMs, fetchQuote]);
1113
- useEffect3(() => {
1114
- if (!autoRefreshMs || !paramsKey) return;
1115
- const interval = setInterval(() => fetchQuote(), autoRefreshMs);
1116
- return () => clearInterval(interval);
1117
- }, [autoRefreshMs, paramsKey, fetchQuote]);
1118
- return useMemo2(
1119
- () => ({
1120
- data,
1121
- loading,
1122
- error,
1123
- warning,
1124
- refetch: fetchQuote
1125
- }),
1126
- [data, loading, error, warning, fetchQuote]
1127
- );
1128
- }
1129
-
1130
- // src/react/useBalances.ts
1131
- import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
1132
- function useBalances(params) {
1133
- const [data, setData] = useState4(null);
1134
- const [loading, setLoading] = useState4(false);
1135
- const [error, setError] = useState4(null);
1136
- const abortRef = useRef4(null);
1137
- const stableParams = useMemo3(() => {
1138
- if (!params) return null;
1139
- const { addresses, cursorEvm, cursorSvm } = params;
1140
- return {
1141
- addresses: {
1142
- evm: addresses?.evm ?? void 0,
1143
- svm: addresses?.svm ?? void 0
1144
- },
1145
- cursorEvm,
1146
- cursorSvm
1147
- };
1148
- }, [params?.addresses?.evm, params?.addresses?.svm, params?.cursorEvm, params?.cursorSvm]);
1149
- const fetchBalances = useCallback3(async () => {
1150
- if (!stableParams) return;
1151
- if (abortRef.current) abortRef.current.abort();
1152
- const controller = new AbortController();
1153
- abortRef.current = controller;
1154
- setLoading(true);
1155
- setError(null);
1156
- try {
1157
- const result = await getBalances(stableParams, { signal: controller.signal });
1158
- setData((prev) => {
1159
- if (JSON.stringify(prev) === JSON.stringify(result)) return prev;
1160
- return result;
1161
- });
1162
- return result;
1163
- } catch (err) {
1164
- if (err.name === "AbortError") return;
1165
- const e = err instanceof Error ? err : new Error(String(err));
1166
- setError(e);
1167
- throw e;
1168
- } finally {
1169
- setLoading(false);
1170
- }
1171
- }, [stableParams]);
1172
- useEffect4(() => {
1173
- if (stableParams) fetchBalances().catch(() => {
1079
+ onStatus,
1080
+ orderType,
1081
+ options
1174
1082
  });
1175
- return () => {
1176
- if (abortRef.current) abortRef.current.abort();
1177
- };
1178
- }, [fetchBalances]);
1179
- return useMemo3(
1180
- () => ({
1181
- /** Latest fetched balance data */
1182
- data,
1183
- /** Whether the hook is currently fetching */
1184
- loading,
1185
- /** Error object if fetching failed */
1186
- error,
1187
- /** Manually trigger a refresh */
1188
- refetch: fetchBalances
1189
- }),
1190
- [data, loading, error, fetchBalances]
1191
- );
1192
- }
1083
+ }
1084
+ /**
1085
+ * Fetches all user orders (Market, Limit, Cross-chain) for connected wallets.
1086
+ *
1087
+ * ---
1088
+ * ### Overview
1089
+ * Retrieves both **single-chain** and **cross-chain** orders from the Shogun Intents API.
1090
+ * Works across EVM, Solana
1091
+ *
1092
+ * ---
1093
+ * @example
1094
+ * ```ts
1095
+ * const orders = await sdk.getOrders({
1096
+ * evmAddress: "0x123...",
1097
+ * solAddress: "9d12hF...abc",
1098
+ * });
1099
+ *
1100
+ * console.log(orders.singleChainLimitOrders);
1101
+ * ```
1102
+ *
1103
+ * @param params - Wallet addresses to fetch orders for (EVM, Solana).
1104
+ * @returns A structured {@link ApiUserOrders} object containing all user orders.
1105
+ */
1106
+ async getOrders(params) {
1107
+ return getOrders(params);
1108
+ }
1109
+ };
1193
1110
  export {
1194
- NATIVE_TOKEN,
1195
- SOLANA_CHAIN_ID,
1111
+ ChainId,
1112
+ OrderExecutionType,
1196
1113
  SupportedChains,
1197
- adaptEthersSigner,
1198
- adaptSolanaWallet,
1199
- adaptViemWallet,
1114
+ SwapSDK,
1200
1115
  buildQuoteParams,
1201
- executeOrder,
1202
- getBalances,
1203
- getQuote,
1204
- getTokenList,
1205
- isNativeAddress,
1206
- isViemWalletClient,
1207
- normalizeEvmTokenAddress,
1208
- serializeBigIntsToStrings,
1209
- useBalances,
1210
- useExecuteOrder,
1211
- useQuote,
1212
- useTokenList
1116
+ isEvmChain
1213
1117
  };