@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/core.cjs CHANGED
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
7
  var __export = (target, all) => {
7
8
  for (var name in all)
8
9
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -16,40 +17,29 @@ var __copyProps = (to, from, except, desc) => {
16
17
  return to;
17
18
  };
18
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
19
21
 
20
22
  // src/core/index.ts
21
23
  var core_exports = {};
22
24
  __export(core_exports, {
23
- ChainID: () => import_intents_sdk10.ChainID,
24
- NATIVE_TOKEN: () => NATIVE_TOKEN,
25
- SOLANA_CHAIN_ID: () => SOLANA_CHAIN_ID,
25
+ ChainId: () => ChainId,
26
+ OrderExecutionType: () => OrderExecutionType,
26
27
  SupportedChains: () => SupportedChains,
28
+ SwapSDK: () => SwapSDK,
27
29
  buildQuoteParams: () => buildQuoteParams,
28
- executeOrder: () => executeOrder,
29
- getBalances: () => getBalances,
30
- getQuote: () => getQuote,
31
- getTokenList: () => getTokenList,
32
- isEvmChain: () => import_intents_sdk10.isEvmChain,
33
- isNativeAddress: () => isNativeAddress,
34
- isViemWalletClient: () => isViemWalletClient,
35
- serializeBigIntsToStrings: () => serializeBigIntsToStrings
30
+ isEvmChain: () => isEvmChain
36
31
  });
37
32
  module.exports = __toCommonJS(core_exports);
38
33
 
39
- // src/core/token-list.ts
40
- var import_intents_sdk = require("@shogun-sdk/intents-sdk");
41
- async function getTokenList(params) {
42
- return (0, import_intents_sdk.getTokenList)(params);
43
- }
44
-
45
34
  // src/core/getQuote.ts
46
- var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
47
- var import_viem = require("viem");
48
-
49
- // src/core/executeOrder/normalizeNative.ts
50
35
  var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
36
+ var import_viem2 = require("viem");
37
+
38
+ // src/core/execute/normalizeNative.ts
39
+ var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
51
40
 
52
41
  // src/utils/address.ts
42
+ var import_viem = require("viem");
53
43
  var NATIVE_TOKEN = {
54
44
  ETH: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
55
45
  SOL: "So11111111111111111111111111111111111111111",
@@ -60,13 +50,32 @@ var isNativeAddress = (tokenAddress) => {
60
50
  const normalizedTokenAddress = tokenAddress.toLowerCase();
61
51
  return !!tokenAddress && NATIVE_ADDRESSES.includes(normalizedTokenAddress);
62
52
  };
53
+ function normalizeEvmTokenAddress(address) {
54
+ const lower = address.toLowerCase();
55
+ return lower === NATIVE_TOKEN.ETH.toLowerCase() ? import_viem.zeroAddress : address;
56
+ }
63
57
 
64
58
  // src/utils/chain.ts
65
- var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
66
- var SOLANA_CHAIN_ID = import_intents_sdk2.ChainID.Solana;
67
- var SupportedChains = [
59
+ var import_intents_sdk = require("@shogun-sdk/intents-sdk");
60
+ var SOLANA_CHAIN_ID = import_intents_sdk.ChainID.Solana;
61
+ var CURRENT_SUPPORTED = [
62
+ import_intents_sdk.ChainID.Solana,
63
+ import_intents_sdk.ChainID.BSC,
64
+ import_intents_sdk.ChainID.Base,
65
+ import_intents_sdk.ChainID.MONAD
66
+ ];
67
+ var ChainId = Object.entries(import_intents_sdk.ChainID).reduce(
68
+ (acc, [key, value]) => {
69
+ if (typeof value === "number" && CURRENT_SUPPORTED.includes(value)) {
70
+ acc[key] = value;
71
+ }
72
+ return acc;
73
+ },
74
+ {}
75
+ );
76
+ var SupportedChainsInternal = [
68
77
  {
69
- id: import_intents_sdk2.ChainID.Arbitrum,
78
+ id: import_intents_sdk.ChainID.Arbitrum,
70
79
  name: "Arbitrum",
71
80
  isEVM: true,
72
81
  wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -75,7 +84,7 @@ var SupportedChains = [
75
84
  tokenAddress: NATIVE_TOKEN.ETH
76
85
  },
77
86
  {
78
- id: import_intents_sdk2.ChainID.Optimism,
87
+ id: import_intents_sdk.ChainID.Optimism,
79
88
  name: "Optimism",
80
89
  isEVM: true,
81
90
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -84,7 +93,7 @@ var SupportedChains = [
84
93
  tokenAddress: NATIVE_TOKEN.ETH
85
94
  },
86
95
  {
87
- id: import_intents_sdk2.ChainID.Base,
96
+ id: import_intents_sdk.ChainID.Base,
88
97
  name: "Base",
89
98
  isEVM: true,
90
99
  wrapped: "0x4200000000000000000000000000000000000006",
@@ -93,7 +102,7 @@ var SupportedChains = [
93
102
  tokenAddress: NATIVE_TOKEN.ETH
94
103
  },
95
104
  {
96
- id: import_intents_sdk2.ChainID.Hyperliquid,
105
+ id: import_intents_sdk.ChainID.Hyperliquid,
97
106
  name: "Hyperliquid",
98
107
  isEVM: true,
99
108
  wrapped: "0x5555555555555555555555555555555555555555",
@@ -102,7 +111,7 @@ var SupportedChains = [
102
111
  tokenAddress: NATIVE_TOKEN.ETH
103
112
  },
104
113
  {
105
- id: import_intents_sdk2.ChainID.BSC,
114
+ id: import_intents_sdk.ChainID.BSC,
106
115
  name: "BSC",
107
116
  isEVM: true,
108
117
  wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
@@ -118,8 +127,21 @@ var SupportedChains = [
118
127
  symbol: "SOL",
119
128
  decimals: 9,
120
129
  tokenAddress: NATIVE_TOKEN.SOL
130
+ },
131
+ {
132
+ id: import_intents_sdk.ChainID.MONAD,
133
+ name: "Monad",
134
+ isEVM: true,
135
+ wrapped: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
136
+ symbol: "MON",
137
+ decimals: 18,
138
+ tokenAddress: NATIVE_TOKEN.ETH
121
139
  }
122
140
  ];
141
+ var SupportedChains = SupportedChainsInternal.filter(
142
+ (c) => CURRENT_SUPPORTED.includes(c.id)
143
+ );
144
+ var isEvmChain = import_intents_sdk.isEvmChain;
123
145
 
124
146
  // src/utils/viem.ts
125
147
  function isViemWalletClient(wallet) {
@@ -147,9 +169,9 @@ function serializeBigIntsToStrings(obj) {
147
169
  return obj;
148
170
  }
149
171
 
150
- // src/core/executeOrder/normalizeNative.ts
172
+ // src/core/execute/normalizeNative.ts
151
173
  function normalizeNative(chainId, address) {
152
- if ((0, import_intents_sdk3.isEvmChain)(chainId) && isNativeAddress(address)) {
174
+ if ((0, import_intents_sdk2.isEvmChain)(chainId) && isNativeAddress(address)) {
153
175
  const chain = SupportedChains.find((c) => c.id === chainId);
154
176
  if (!chain?.wrapped)
155
177
  throw new Error(`Wrapped token not found for chainId ${chainId}`);
@@ -160,39 +182,72 @@ function normalizeNative(chainId, address) {
160
182
 
161
183
  // src/core/getQuote.ts
162
184
  async function getQuote(params) {
185
+ const amount = BigInt(params.amount);
163
186
  if (!params.tokenIn?.address || !params.tokenOut?.address) {
164
187
  throw new Error("Both tokenIn and tokenOut must include an address.");
165
188
  }
166
189
  if (!params.sourceChainId || !params.destChainId) {
167
190
  throw new Error("Both sourceChainId and destChainId are required.");
168
191
  }
169
- if (params.amount <= 0n) {
192
+ if (amount <= 0n) {
170
193
  throw new Error("Amount must be greater than 0.");
171
194
  }
172
- const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
173
- const data = await import_intents_sdk4.QuoteProvider.getQuote({
174
- sourceChainId: params.sourceChainId,
175
- destChainId: params.destChainId,
176
- tokenIn: normalizedTokenIn,
177
- tokenOut: params.tokenOut.address,
178
- amount: params.amount
179
- });
180
- const inputSlippage = params.slippage ?? 5;
181
- const slippageDecimal = inputSlippage / 100;
182
- const slippage = Math.min(Math.max(slippageDecimal, 0), 0.5);
195
+ const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
196
+ const slippageBps = BigInt(Math.round(slippagePercent * 100));
197
+ const applyUserSlippage = (value) => value * (10000n - slippageBps) / 10000n;
183
198
  let warning;
184
- if (slippage > 0.1) {
185
- warning = `\u26A0\uFE0F High slippage tolerance (${(slippage * 100).toFixed(2)}%) \u2014 price may vary significantly.`;
199
+ if (slippagePercent > 10) {
200
+ warning = `\u26A0\uFE0F High slippage tolerance (${slippagePercent.toFixed(2)}%) \u2014 price may vary significantly.`;
186
201
  }
187
- const estimatedAmountOut = BigInt(data.estimatedAmountOutReduced);
188
- const slippageBps = BigInt(Math.round(slippage * 1e4));
189
- const estimatedAmountOutAfterSlippage = estimatedAmountOut * (10000n - slippageBps) / 10000n;
190
- const pricePerInputToken = estimatedAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / BigInt(params.amount);
202
+ const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
203
+ const isSingleChain = params.sourceChainId === params.destChainId;
204
+ let data;
205
+ let netFloor;
206
+ let minStablecoinsAmount;
207
+ if (isSingleChain) {
208
+ const { quote, netAmountOut } = await import_intents_sdk3.QuoteProvider.getSingleChainNetQuote({
209
+ chainId: params.sourceChainId,
210
+ amount,
211
+ tokenIn: normalizedTokenIn,
212
+ tokenOut: params.tokenOut.address
213
+ });
214
+ netFloor = netAmountOut;
215
+ minStablecoinsAmount = 0n;
216
+ data = {
217
+ amountInUsd: quote.amountInUsd,
218
+ estimatedAmountInAsMinStablecoinAmount: 0n,
219
+ estimatedAmountOut: quote.amountOut,
220
+ estimatedAmountOutUsd: quote.amountOutUsd,
221
+ // filled in below once the user slippage buffer is known
222
+ estimatedAmountOutReduced: netAmountOut,
223
+ estimatedAmountOutUsdReduced: quote.amountOutUsd,
224
+ tokenIn: { address: params.tokenIn.address, chainId: params.sourceChainId },
225
+ tokenOut: { address: params.tokenOut.address, chainId: params.destChainId }
226
+ };
227
+ } else {
228
+ const crossChainQuote = await import_intents_sdk3.QuoteProvider.getCrossChainNetQuote({
229
+ sourceChainId: params.sourceChainId,
230
+ destChainId: params.destChainId,
231
+ tokenIn: normalizedTokenIn,
232
+ tokenOut: params.tokenOut.address,
233
+ amount
234
+ });
235
+ data = crossChainQuote;
236
+ netFloor = BigInt(crossChainQuote.estimatedAmountOutReduced);
237
+ minStablecoinsAmount = applyUserSlippage(
238
+ BigInt(crossChainQuote.estimatedAmountInAsMinStablecoinAmount)
239
+ );
240
+ }
241
+ const amountOut = applyUserSlippage(netFloor);
242
+ const grossAmountOut = BigInt(data.estimatedAmountOut);
243
+ const pricePerTokenOutInUsd = grossAmountOut > 0n ? data.estimatedAmountOutUsd / Number(grossAmountOut) : 0;
244
+ const amountOutUsd = Number(amountOut) * pricePerTokenOutInUsd;
245
+ const pricePerInputToken = grossAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / amount;
191
246
  return {
192
- amountOut: estimatedAmountOut,
193
- amountOutUsd: data.estimatedAmountOutUsd,
247
+ amountOut,
248
+ amountOutUsd,
194
249
  amountInUsd: data.amountInUsd,
195
- minStablecoinsAmount: data.estimatedAmountInAsMinStablecoinAmount,
250
+ minStablecoinsAmount,
196
251
  tokenIn: {
197
252
  address: params.tokenIn.address,
198
253
  decimals: params.tokenIn.decimals ?? 18,
@@ -203,12 +258,13 @@ async function getQuote(params) {
203
258
  decimals: params.tokenOut.decimals ?? 18,
204
259
  chainId: params.destChainId
205
260
  },
206
- amountIn: params.amount,
261
+ amountIn: amount,
207
262
  pricePerInputToken,
208
- slippage,
263
+ slippage: slippagePercent,
209
264
  internal: {
210
265
  ...data,
211
- estimatedAmountOutReduced: estimatedAmountOutAfterSlippage
266
+ estimatedAmountOutReduced: amountOut,
267
+ estimatedAmountOutUsdReduced: amountOutUsd
212
268
  },
213
269
  warning
214
270
  };
@@ -226,13 +282,13 @@ function buildQuoteParams({
226
282
  tokenOut,
227
283
  sourceChainId,
228
284
  destChainId,
229
- amount: (0, import_viem.parseUnits)(amount.toString(), tokenIn.decimals ?? 18),
285
+ amount: (0, import_viem2.parseUnits)(amount.toString(), tokenIn.decimals ?? 18).toString(),
230
286
  slippage
231
287
  };
232
288
  }
233
289
 
234
290
  // src/core/getBalances.ts
235
- var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
291
+ var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
236
292
  async function getBalances(params, options) {
237
293
  const { addresses, cursorEvm, cursorSvm } = params;
238
294
  const { signal } = options ?? {};
@@ -245,7 +301,7 @@ async function getBalances(params, options) {
245
301
  cursorSvm
246
302
  });
247
303
  const start = performance.now();
248
- const response = await fetch(`${import_intents_sdk5.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
304
+ const response = await fetch(`${import_intents_sdk4.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
249
305
  method: "POST",
250
306
  headers: {
251
307
  accept: "application/json",
@@ -273,21 +329,67 @@ async function getBalances(params, options) {
273
329
  const evmItems = data.evm?.items ?? [];
274
330
  const svmItems = data.svm?.items ?? [];
275
331
  const combined = [...evmItems, ...svmItems];
332
+ const filtered = combined.filter(
333
+ (b) => CURRENT_SUPPORTED.includes(b.chainId)
334
+ );
276
335
  return {
277
- results: combined,
336
+ results: filtered,
278
337
  nextCursorEvm: data.evm?.cursor ?? null,
279
338
  nextCursorSvm: data.svm?.cursor ?? null
280
339
  };
281
340
  }
282
341
 
283
- // src/core/executeOrder/execute.ts
284
- var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
285
- var import_viem4 = require("viem");
342
+ // src/core/token-list.ts
343
+ var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
344
+ async function getTokenList(params) {
345
+ const url = new URL(`${import_intents_sdk5.TOKEN_SEARCH_API_BASE_URL}/tokens/search`);
346
+ if (params.q) url.searchParams.append("q", params.q);
347
+ if (params.networkId) url.searchParams.append("networkId", String(params.networkId));
348
+ if (params.page) url.searchParams.append("page", String(params.page));
349
+ if (params.limit) url.searchParams.append("limit", String(params.limit));
350
+ const res = await fetch(url.toString(), {
351
+ signal: params.signal
352
+ });
353
+ if (!res.ok) {
354
+ throw new Error(`Failed to fetch tokens: ${res.status} ${res.statusText}`);
355
+ }
356
+ const data = await res.json();
357
+ const filteredResults = data.results.filter(
358
+ (token) => CURRENT_SUPPORTED.includes(token.chainId)
359
+ );
360
+ return {
361
+ ...data,
362
+ results: filteredResults,
363
+ count: filteredResults.length
364
+ };
365
+ }
366
+
367
+ // src/core/token.ts
368
+ var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
369
+ async function getTokensData(addresses) {
370
+ if (!addresses?.length) return [];
371
+ const response = await fetch(`${import_intents_sdk6.TOKEN_SEARCH_API_BASE_URL}/tokens/tokens`, {
372
+ method: "POST",
373
+ headers: {
374
+ "Content-Type": "application/json",
375
+ accept: "*/*"
376
+ },
377
+ body: JSON.stringify({ addresses })
378
+ });
379
+ if (!response.ok) {
380
+ throw new Error(`Failed to fetch token data: ${response.statusText}`);
381
+ }
382
+ const data = await response.json();
383
+ const filtered = data.filter((t) => CURRENT_SUPPORTED.includes(Number(t.chainId)));
384
+ return filtered;
385
+ }
386
+
387
+ // src/core/execute/execute.ts
388
+ var import_intents_sdk12 = require("@shogun-sdk/intents-sdk");
389
+ var import_viem7 = require("viem");
286
390
 
287
391
  // src/wallet-adapter/evm-wallet-adapter/adapter.ts
288
- var import_ethers = require("ethers/lib/ethers.js");
289
- var import_utils2 = require("ethers/lib/utils.js");
290
- var import_viem2 = require("viem");
392
+ var import_viem3 = require("viem");
291
393
  function isEVMTransaction(tx) {
292
394
  return typeof tx.from === "string";
293
395
  }
@@ -305,15 +407,26 @@ var adaptViemWallet = (wallet) => {
305
407
  if (!isEVMTransaction(transaction)) {
306
408
  throw new Error("Expected EVMTransaction but got SolanaTransaction");
307
409
  }
308
- const tx = await wallet.sendTransaction({
309
- from: transaction.from,
310
- to: transaction.to,
311
- data: transaction.data,
312
- value: transaction.value,
313
- account: wallet.account?.address,
314
- chain: wallet.chain
315
- });
316
- return tx;
410
+ if (wallet.transport.type === "http") {
411
+ const request = await wallet.prepareTransactionRequest({
412
+ to: transaction.to,
413
+ data: transaction.data,
414
+ value: transaction.value,
415
+ chain: wallet.chain
416
+ });
417
+ const serializedTransaction = await wallet.signTransaction(request);
418
+ const tx = await wallet.sendRawTransaction({ serializedTransaction });
419
+ return tx;
420
+ } else {
421
+ const hash = await wallet.sendTransaction({
422
+ to: transaction.to,
423
+ data: transaction.data,
424
+ value: transaction.value,
425
+ chain: wallet.chain,
426
+ account: wallet.account
427
+ });
428
+ return hash;
429
+ }
317
430
  };
318
431
  const switchChain = async (chainId) => {
319
432
  try {
@@ -336,55 +449,96 @@ var adaptViemWallet = (wallet) => {
336
449
  if (!addr) throw new Error("No address found");
337
450
  return addr;
338
451
  };
452
+ const readContract = async ({
453
+ address: address2,
454
+ abi,
455
+ functionName,
456
+ args = []
457
+ }) => {
458
+ const publicClient = wallet.extend(import_viem3.publicActions);
459
+ return await publicClient.readContract({
460
+ address: address2,
461
+ abi,
462
+ functionName,
463
+ args
464
+ });
465
+ };
339
466
  return {
340
467
  vmType: "EVM" /* EVM */,
341
- transport: (0, import_viem2.custom)(wallet.transport),
468
+ transport: (0, import_viem3.custom)(wallet.transport),
342
469
  getChainId: async () => wallet.getChainId(),
343
470
  address,
344
471
  sendTransaction,
345
472
  signTypedData,
346
- switchChain
473
+ switchChain,
474
+ readContract
347
475
  };
348
476
  };
349
477
 
350
- // src/core/executeOrder/handleEvmExecution.ts
351
- var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
352
- var import_viem3 = require("viem");
478
+ // src/core/execute/handleEvmExecution.ts
479
+ var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
480
+ var import_viem6 = require("viem");
353
481
 
354
- // src/core/executeOrder/stageMessages.ts
482
+ // src/core/execute/stageMessages.ts
355
483
  var DEFAULT_STAGE_MESSAGES = {
356
484
  processing: "Preparing transaction for execution",
357
485
  approving: "Approving token allowance",
358
486
  approved: "Token approved successfully",
359
- signing: "Signing order for submission",
360
- submitting: "Submitting order to Auctioneer",
361
- success: "Order executed successfully",
362
- error: "Order execution failed"
487
+ signing: "Signing transaction for submission",
488
+ submitting: "Submitting transaction",
489
+ initiated: "Transaction initiated.",
490
+ success: "Transaction Executed successfully",
491
+ success_limit: "Limit order has been submitted successfully.",
492
+ shogun_processing: "Shogun is processing your transaction",
493
+ error: "Transaction failed during submission"
363
494
  };
364
495
 
365
- // src/core/executeOrder/buildOrder.ts
366
- var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
496
+ // src/core/execute/buildOrder.ts
497
+ var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
498
+ var import_viem4 = require("viem");
499
+
500
+ // src/utils/order.ts
501
+ var OrderExecutionType = /* @__PURE__ */ ((OrderExecutionType2) => {
502
+ OrderExecutionType2["LIMIT"] = "limit";
503
+ OrderExecutionType2["MARKET"] = "market";
504
+ return OrderExecutionType2;
505
+ })(OrderExecutionType || {});
506
+
507
+ // src/core/execute/buildOrder.ts
367
508
  async function buildOrder({
368
509
  quote,
369
510
  accountAddress,
370
511
  destination,
371
512
  deadline,
372
- isSingleChain
513
+ isSingleChain,
514
+ orderType,
515
+ options
373
516
  }) {
374
517
  const { tokenIn, tokenOut } = quote;
518
+ let amountOutMin = BigInt(quote.internal.estimatedAmountOutReduced);
519
+ if (orderType === "limit" /* LIMIT */ && options && "executionPrice" in options) {
520
+ const executionPrice = Number(options.executionPrice);
521
+ if (Number.isFinite(executionPrice) && executionPrice > 0) {
522
+ const decimalsIn = tokenIn.decimals ?? 18;
523
+ const decimalsOut = tokenOut.decimals ?? 18;
524
+ const formattedAmountIn = Number((0, import_viem4.formatUnits)(BigInt(quote.amountIn.toString()), decimalsIn));
525
+ const rawAmountOut = formattedAmountIn * executionPrice;
526
+ amountOutMin = (0, import_viem4.parseUnits)(rawAmountOut.toString(), decimalsOut);
527
+ }
528
+ }
375
529
  if (isSingleChain) {
376
- return await import_intents_sdk6.SingleChainOrder.create({
530
+ return await import_intents_sdk7.SingleChainOrder.create({
377
531
  user: accountAddress,
378
532
  chainId: tokenIn.chainId,
379
533
  tokenIn: tokenIn.address,
380
534
  tokenOut: tokenOut.address,
381
535
  amountIn: quote.amountIn,
382
- amountOutMin: quote.internal.estimatedAmountOutReduced,
536
+ amountOutMin,
383
537
  deadline,
384
538
  destinationAddress: destination
385
539
  });
386
540
  }
387
- return await import_intents_sdk6.CrossChainOrder.create({
541
+ return await import_intents_sdk7.CrossChainOrder.create({
388
542
  user: accountAddress,
389
543
  sourceChainId: tokenIn.chainId,
390
544
  sourceTokenAddress: tokenIn.address,
@@ -393,12 +547,166 @@ async function buildOrder({
393
547
  destinationTokenAddress: tokenOut.address,
394
548
  destinationAddress: destination,
395
549
  deadline,
396
- destinationTokenMinAmount: quote.internal.estimatedAmountOutReduced,
550
+ destinationTokenMinAmount: amountOutMin,
397
551
  minStablecoinAmount: quote.minStablecoinsAmount
398
552
  });
399
553
  }
400
554
 
401
- // src/core/executeOrder/handleEvmExecution.ts
555
+ // src/utils/pollOrderStatus.ts
556
+ var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
557
+ async function pollOrderStatus(address, orderId, options = {}) {
558
+ const { intervalMs = 2e3, timeoutMs = 3e5, authToken } = options;
559
+ const startTime = Date.now();
560
+ const isDebug = process.env.NODE_ENV !== "production";
561
+ const isEvmAddress = /^0x[a-fA-F0-9]{40}$/.test(address);
562
+ const isSuiAddress = /^0x[a-fA-F0-9]{64}$/.test(address);
563
+ const isSolanaAddress = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
564
+ let queryParam;
565
+ if (isEvmAddress) queryParam = `evmWallets=${address}`;
566
+ else if (isSuiAddress) queryParam = `suiWallets=${address}`;
567
+ else if (isSolanaAddress) queryParam = `solanaWallets=${address}`;
568
+ else throw new Error(`Unrecognized wallet address format: ${address}`);
569
+ const queryUrl = `${import_intents_sdk8.AUCTIONEER_URL}/user_intent?${queryParam}`;
570
+ return new Promise((resolve, reject) => {
571
+ const pollInterval = setInterval(async () => {
572
+ try {
573
+ if (Date.now() - startTime > timeoutMs) {
574
+ clearInterval(pollInterval);
575
+ return resolve("Timeout");
576
+ }
577
+ const res = await fetch(queryUrl, {
578
+ method: "GET",
579
+ headers: {
580
+ "Content-Type": "application/json",
581
+ // The /user_intent status endpoint requires the SIWE JWT; without it
582
+ // the request 401s after the order has already been submitted.
583
+ ...authToken ? { Authorization: `Bearer ${authToken}` } : {}
584
+ }
585
+ });
586
+ if (!res.ok) {
587
+ clearInterval(pollInterval);
588
+ return reject(
589
+ new Error(`Failed to fetch orders: ${res.status} ${res.statusText}`)
590
+ );
591
+ }
592
+ const json = await res.json();
593
+ const data = json?.data ?? {};
594
+ const allOrders = [
595
+ ...data.crossChainDcaOrders ?? [],
596
+ ...data.crossChainLimitOrders ?? [],
597
+ ...data.singleChainDcaOrders ?? [],
598
+ ...data.singleChainLimitOrders ?? []
599
+ ];
600
+ const targetOrder = allOrders.find((o) => o.orderId === orderId);
601
+ if (!targetOrder) {
602
+ if (isDebug)
603
+ console.debug(`[pollOrderStatus] [${orderId}] Not found yet`);
604
+ return;
605
+ }
606
+ const { orderStatus } = targetOrder;
607
+ if (isDebug) {
608
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
609
+ console.debug(`targetOrder`, targetOrder);
610
+ console.debug(
611
+ `[pollOrderStatus] [${orderId}] status=${orderStatus} (elapsed ${elapsed}s)`
612
+ );
613
+ }
614
+ if (["Fulfilled", "Cancelled", "Outdated"].includes(orderStatus)) {
615
+ clearInterval(pollInterval);
616
+ return resolve(orderStatus);
617
+ }
618
+ } catch (error) {
619
+ clearInterval(pollInterval);
620
+ return reject(error);
621
+ }
622
+ }, intervalMs);
623
+ });
624
+ }
625
+
626
+ // src/core/execute/handleOrderPollingResult.ts
627
+ async function handleOrderPollingResult({
628
+ status,
629
+ orderId,
630
+ chainId,
631
+ update,
632
+ messageFor
633
+ }) {
634
+ switch (status) {
635
+ case "Fulfilled":
636
+ update("success", messageFor("success"));
637
+ return {
638
+ status: true,
639
+ orderId,
640
+ chainId,
641
+ finalStatus: status,
642
+ stage: "success"
643
+ };
644
+ case "Cancelled":
645
+ update("error", "Order was cancelled before fulfillment");
646
+ break;
647
+ case "Timeout":
648
+ update("error", "Order polling timed out");
649
+ break;
650
+ case "NotFound":
651
+ default:
652
+ update("error", "Order not found");
653
+ break;
654
+ }
655
+ return {
656
+ status: false,
657
+ orderId,
658
+ chainId,
659
+ finalStatus: status,
660
+ stage: "error"
661
+ };
662
+ }
663
+
664
+ // src/core/execute/ensurePermit2Allowance.ts
665
+ var import_viem5 = require("viem");
666
+ var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
667
+ async function ensurePermit2Allowance({
668
+ chainId,
669
+ tokenIn,
670
+ wallet,
671
+ accountAddress,
672
+ requiredAmount,
673
+ increaseByDelta = false
674
+ }) {
675
+ const spender = import_intents_sdk9.PERMIT2_ADDRESS[chainId];
676
+ let currentAllowance = 0n;
677
+ try {
678
+ if (!wallet.readContract) {
679
+ throw new Error("Wallet does not implement readContract()");
680
+ }
681
+ currentAllowance = await wallet.readContract({
682
+ address: tokenIn,
683
+ abi: import_viem5.erc20Abi,
684
+ functionName: "allowance",
685
+ args: [accountAddress, spender]
686
+ });
687
+ } catch (error) {
688
+ console.warn(`[Permit2] Failed to read allowance for ${tokenIn}`, error);
689
+ }
690
+ const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount : import_viem5.maxUint256;
691
+ console.debug(
692
+ `[Permit2] Approving ${approvalAmount} for ${tokenIn} (current: ${currentAllowance}, required: ${requiredAmount})`
693
+ );
694
+ await wallet.sendTransaction({
695
+ to: tokenIn,
696
+ from: accountAddress,
697
+ data: (0, import_viem5.encodeFunctionData)({
698
+ abi: import_viem5.erc20Abi,
699
+ functionName: "approve",
700
+ args: [spender, approvalAmount]
701
+ }),
702
+ value: 0n
703
+ });
704
+ console.info(
705
+ `[Permit2] Approval transaction sent for ${tokenIn} on chain ${chainId}`
706
+ );
707
+ }
708
+
709
+ // src/core/execute/handleEvmExecution.ts
402
710
  async function handleEvmExecution({
403
711
  recipientAddress,
404
712
  quote,
@@ -406,18 +714,22 @@ async function handleEvmExecution({
406
714
  accountAddress,
407
715
  wallet,
408
716
  isSingleChain,
409
- deadline,
410
- update
717
+ update,
718
+ orderType,
719
+ options
411
720
  }) {
412
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
721
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
722
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
413
723
  await wallet.switchChain(chainId);
414
724
  const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
725
+ quote.tokenOut.address = normalizeEvmTokenAddress(quote.tokenOut.address);
415
726
  const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
416
727
  update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
417
728
  if (shouldWrapNative) {
729
+ quote.tokenIn.address === tokenIn;
418
730
  await wallet.sendTransaction({
419
731
  to: tokenIn,
420
- data: (0, import_viem3.encodeFunctionData)({
732
+ data: (0, import_viem6.encodeFunctionData)({
421
733
  abi: [{ type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] }],
422
734
  functionName: "deposit",
423
735
  args: []
@@ -426,43 +738,70 @@ async function handleEvmExecution({
426
738
  from: accountAddress
427
739
  });
428
740
  }
429
- update("approving", messageFor("approving"));
430
- await wallet.sendTransaction({
431
- to: tokenIn,
432
- data: (0, import_viem3.encodeFunctionData)({
433
- abi: import_viem3.erc20Abi,
434
- functionName: "approve",
435
- args: [import_intents_sdk7.PERMIT2_ADDRESS[chainId], BigInt(quote.amountIn)]
436
- }),
437
- value: 0n,
438
- from: accountAddress
741
+ update("processing", messageFor("approving"));
742
+ await ensurePermit2Allowance({
743
+ chainId,
744
+ tokenIn,
745
+ wallet,
746
+ accountAddress,
747
+ requiredAmount: BigInt(quote.amountIn)
439
748
  });
440
- update("approved", messageFor("approved"));
749
+ update("processing", messageFor("approved"));
441
750
  const destination = recipientAddress ?? accountAddress;
442
751
  const order = await buildOrder({
443
752
  quote,
444
753
  accountAddress,
445
754
  destination,
446
755
  deadline,
447
- isSingleChain
756
+ isSingleChain,
757
+ orderType,
758
+ options
448
759
  });
449
- update("signing", messageFor("signing"));
450
- const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk7.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk7.getEVMCrossChainOrderTypedData)(order);
760
+ console.debug(`order`, order);
761
+ update("processing", messageFor("signing"));
762
+ const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk10.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk10.getEVMCrossChainOrderTypedData)(order);
763
+ const typedData = serializeBigIntsToStrings(orderTypedData);
451
764
  if (!wallet.signTypedData) {
452
765
  throw new Error("Wallet does not support EIP-712 signing");
453
766
  }
454
- const signature = await wallet.signTypedData(serializeBigIntsToStrings(orderTypedData));
455
- update("submitting", messageFor("submitting"));
767
+ const signature = await wallet.signTypedData({
768
+ domain: typedData.domain,
769
+ types: typedData.types,
770
+ primaryType: typedData.primaryType,
771
+ value: typedData.message,
772
+ message: typedData.message
773
+ });
774
+ update("processing", messageFor("submitting"));
456
775
  const res = await order.sendToAuctioneer({ signature, nonce: nonce.toString() });
457
776
  if (!res.success) {
458
777
  throw new Error("Auctioneer submission failed");
459
778
  }
460
- update("success", messageFor("success"));
461
- return { status: true, txHash: res.data, chainId, stage: "success" };
779
+ update("initiated", messageFor("initiated"));
780
+ const { intentId: orderId } = res.data;
781
+ update("initiated", messageFor("shogun_processing"));
782
+ if (orderType === "limit" /* LIMIT */) {
783
+ update("success", messageFor("success_limit"));
784
+ return {
785
+ status: true,
786
+ orderId,
787
+ chainId,
788
+ finalStatus: "OrderPlaced",
789
+ stage: "success"
790
+ };
791
+ } else {
792
+ const status = await pollOrderStatus(accountAddress, orderId, { authToken: options?.authToken });
793
+ return await handleOrderPollingResult({
794
+ status,
795
+ orderId,
796
+ chainId,
797
+ update,
798
+ messageFor
799
+ });
800
+ }
462
801
  }
463
802
 
464
- // src/core/executeOrder/handleSolanaExecution.ts
465
- var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
803
+ // src/core/execute/handleSolanaExecution.ts
804
+ var import_intents_sdk11 = require("@shogun-sdk/intents-sdk");
466
805
  var import_web3 = require("@solana/web3.js");
467
806
  async function handleSolanaExecution({
468
807
  recipientAddress,
@@ -471,12 +810,14 @@ async function handleSolanaExecution({
471
810
  isSingleChain,
472
811
  update,
473
812
  accountAddress,
474
- deadline
813
+ orderType,
814
+ options
475
815
  }) {
476
816
  if (!wallet.rpcUrl) {
477
817
  throw new Error("Solana wallet is missing rpcUrl");
478
818
  }
479
- const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
819
+ const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
820
+ const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
480
821
  update("processing", messageFor("processing"));
481
822
  const destination = recipientAddress ?? accountAddress;
482
823
  const order = await buildOrder({
@@ -484,7 +825,9 @@ async function handleSolanaExecution({
484
825
  accountAddress,
485
826
  destination,
486
827
  deadline,
487
- isSingleChain
828
+ isSingleChain,
829
+ orderType,
830
+ options
488
831
  });
489
832
  const txData = await getSolanaOrderInstructions({
490
833
  order,
@@ -492,10 +835,9 @@ async function handleSolanaExecution({
492
835
  rpcUrl: wallet.rpcUrl
493
836
  });
494
837
  const transaction = import_web3.VersionedTransaction.deserialize(Uint8Array.from(txData.txBytes));
495
- update("signing", messageFor("signing"));
496
- console.log({ order });
497
- const txSignature = await wallet.sendTransaction(transaction);
498
- update("submitting", messageFor("submitting"));
838
+ update("processing", messageFor("signing"));
839
+ await wallet.sendTransaction(transaction);
840
+ update("processing", messageFor("submitting"));
499
841
  const response = await submitToAuctioneer({
500
842
  order,
501
843
  isSingleChain,
@@ -504,13 +846,28 @@ async function handleSolanaExecution({
504
846
  if (!response.success) {
505
847
  throw new Error("Auctioneer submission failed");
506
848
  }
507
- update("success", messageFor("success"));
508
- return {
509
- status: true,
510
- txHash: txSignature,
511
- chainId: import_intents_sdk8.ChainID.Solana,
512
- stage: "success"
513
- };
849
+ update("initiated", messageFor("initiated"));
850
+ const { intentId: orderId } = response.data;
851
+ update("initiated", messageFor("shogun_processing"));
852
+ if (orderType === "limit" /* LIMIT */) {
853
+ update("success", messageFor("success_limit"));
854
+ return {
855
+ status: true,
856
+ orderId,
857
+ chainId: SOLANA_CHAIN_ID,
858
+ finalStatus: "OrderPlaced",
859
+ stage: "success"
860
+ };
861
+ } else {
862
+ const status = await pollOrderStatus(accountAddress, orderId, { authToken: options?.authToken });
863
+ return await handleOrderPollingResult({
864
+ status,
865
+ orderId,
866
+ chainId: SOLANA_CHAIN_ID,
867
+ update,
868
+ messageFor
869
+ });
870
+ }
514
871
  }
515
872
  async function getSolanaOrderInstructions({
516
873
  order,
@@ -518,11 +875,11 @@ async function getSolanaOrderInstructions({
518
875
  rpcUrl
519
876
  }) {
520
877
  if (isSingleChain) {
521
- return await (0, import_intents_sdk8.getSolanaSingleChainOrderInstructions)(order, {
878
+ return await (0, import_intents_sdk11.getSolanaSingleChainOrderInstructions)(order, {
522
879
  rpcUrl
523
880
  });
524
881
  }
525
- return await (0, import_intents_sdk8.getSolanaCrossChainOrderInstructions)(order, {
882
+ return await (0, import_intents_sdk11.getSolanaCrossChainOrderInstructions)(order, {
526
883
  rpcUrl
527
884
  });
528
885
  }
@@ -543,52 +900,93 @@ async function submitToAuctioneer({
543
900
  });
544
901
  }
545
902
 
546
- // src/core/executeOrder/execute.ts
903
+ // src/core/execute/execute.ts
547
904
  async function executeOrder({
548
905
  quote,
549
906
  accountAddress,
550
907
  recipientAddress,
551
908
  wallet,
552
909
  onStatus,
910
+ orderType = "market" /* MARKET */,
553
911
  options = {}
554
912
  }) {
555
- const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
913
+ const isDev = process.env.NODE_ENV !== "production";
914
+ const log = (...args) => {
915
+ if (isDev) console.debug("[OneShot::executeOrder]", ...args);
916
+ };
556
917
  const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
557
- const update = (stage, message) => onStatus?.(stage, message ?? messageFor(stage));
918
+ const update = (stage, message) => {
919
+ log("Stage:", stage, "| Message:", message ?? messageFor(stage));
920
+ onStatus?.(stage, message ?? messageFor(stage));
921
+ };
558
922
  try {
923
+ log("Starting execution:", {
924
+ accountAddress,
925
+ recipientAddress,
926
+ tokenIn: quote?.tokenIn,
927
+ tokenOut: quote?.tokenOut
928
+ });
559
929
  const adapter = normalizeWallet(wallet);
560
930
  if (!adapter) throw new Error("No wallet provided");
561
931
  const { tokenIn, tokenOut } = quote;
932
+ const srcChain = Number(tokenIn.chainId);
933
+ const destChain = Number(tokenOut.chainId);
934
+ if (!CURRENT_SUPPORTED.includes(srcChain) || !CURRENT_SUPPORTED.includes(destChain)) {
935
+ const unsupportedChains = [
936
+ !CURRENT_SUPPORTED.includes(srcChain) ? srcChain : null,
937
+ !CURRENT_SUPPORTED.includes(destChain) ? destChain : null
938
+ ].filter(Boolean).join(", ");
939
+ const errorMsg = `Unsupported chain(s): ${unsupportedChains}`;
940
+ update("error", errorMsg);
941
+ log("Error:", errorMsg);
942
+ throw new Error(errorMsg);
943
+ }
562
944
  const isSingleChain = tokenIn.chainId === tokenOut.chainId;
563
945
  const chainId = Number(tokenIn.chainId);
564
- update("processing", messageFor("processing"));
565
- if ((0, import_intents_sdk9.isEvmChain)(chainId)) {
566
- return await handleEvmExecution({
946
+ update("processing");
947
+ if ((0, import_intents_sdk12.isEvmChain)(chainId)) {
948
+ log("Detected EVM chain:", chainId);
949
+ const result = await handleEvmExecution({
567
950
  recipientAddress,
568
951
  quote,
569
952
  chainId,
570
953
  accountAddress,
571
954
  wallet: adapter,
572
955
  isSingleChain,
573
- deadline,
574
- update
956
+ update,
957
+ orderType,
958
+ options
575
959
  });
960
+ log("EVM execution result:", result);
961
+ return result;
576
962
  }
577
- if (chainId === import_intents_sdk9.ChainID.Solana) {
578
- return await handleSolanaExecution({
963
+ if (chainId === import_intents_sdk12.ChainID.Solana) {
964
+ log("Detected Solana chain");
965
+ const result = await handleSolanaExecution({
579
966
  recipientAddress,
580
967
  quote,
581
968
  accountAddress,
582
969
  wallet: adapter,
583
970
  isSingleChain,
584
- deadline,
585
- update
971
+ update,
972
+ orderType,
973
+ options
586
974
  });
975
+ log("Solana execution result:", result);
976
+ return result;
587
977
  }
588
- update("error", "Unsupported chain");
589
- return { status: false, message: "Unsupported chain", stage: "error" };
978
+ const unsupported = `Unsupported chain: ${chainId}`;
979
+ update("error", unsupported);
980
+ log("Error:", unsupported);
981
+ return { status: false, message: unsupported, stage: "error" };
590
982
  } catch (error) {
591
- const message = error instanceof import_viem4.BaseError ? error.shortMessage : error instanceof Error ? error.message : String(error);
983
+ let message = "An unknown error occurred";
984
+ if (error && typeof error === "object") {
985
+ const err = error;
986
+ message = err.details ?? err.message ?? message;
987
+ } else if (typeof error === "string") {
988
+ message = error;
989
+ }
592
990
  update("error", message);
593
991
  return { status: false, message, stage: "error" };
594
992
  }
@@ -599,21 +997,508 @@ function normalizeWallet(wallet) {
599
997
  return wallet;
600
998
  }
601
999
 
602
- // src/core/index.ts
603
- var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
604
- // Annotate the CommonJS export names for ESM import in node:
605
- 0 && (module.exports = {
606
- ChainID,
607
- NATIVE_TOKEN,
608
- SOLANA_CHAIN_ID,
609
- SupportedChains,
610
- buildQuoteParams,
611
- executeOrder,
612
- getBalances,
613
- getQuote,
614
- getTokenList,
615
- isEvmChain,
616
- isNativeAddress,
617
- isViemWalletClient,
618
- serializeBigIntsToStrings
619
- });
1000
+ // src/core/orders/getOrders.ts
1001
+ var import_intents_sdk13 = require("@shogun-sdk/intents-sdk");
1002
+ async function getOrders({
1003
+ evmAddress,
1004
+ solAddress
1005
+ }) {
1006
+ const wallets = [evmAddress, solAddress].filter(
1007
+ (wallet) => Boolean(wallet)
1008
+ );
1009
+ if (wallets.length === 0) {
1010
+ throw new Error("At least one wallet address (EVM, Solana) must be provided.");
1011
+ }
1012
+ const results = await Promise.all(
1013
+ wallets.map((wallet) => (0, import_intents_sdk13.fetchUserOrders)({ wallet }))
1014
+ );
1015
+ return results.reduce(
1016
+ (merged, orders) => {
1017
+ merged.singleChainLimitOrders.push(...orders.singleChainLimitOrders);
1018
+ merged.crossChainLimitOrders.push(...orders.crossChainLimitOrders);
1019
+ return merged;
1020
+ },
1021
+ { singleChainLimitOrders: [], crossChainLimitOrders: [] }
1022
+ );
1023
+ }
1024
+
1025
+ // src/core/orders/cancelOrder.ts
1026
+ var import_intents_sdk14 = require("@shogun-sdk/intents-sdk");
1027
+ var import_web32 = require("@solana/web3.js");
1028
+ var import_viem8 = require("viem");
1029
+ var inFlightCancels = /* @__PURE__ */ new Map();
1030
+ function cancelIntentsOrder(args) {
1031
+ const srcChain = "srcChainId" in args.order ? args.order.srcChainId : args.order.chainId;
1032
+ const key = `${srcChain}:${args.order.orderId}`;
1033
+ const existing = inFlightCancels.get(key);
1034
+ if (existing) return existing;
1035
+ const pending = performCancel(args).finally(() => {
1036
+ inFlightCancels.delete(key);
1037
+ });
1038
+ inFlightCancels.set(key, pending);
1039
+ return pending;
1040
+ }
1041
+ async function performCancel({
1042
+ order,
1043
+ wallet,
1044
+ sol_rpc
1045
+ }) {
1046
+ const isCrossChain = "srcChainId" in order && "destChainId" in order && order.srcChainId !== order.destChainId;
1047
+ const srcChain = "srcChainId" in order ? order.srcChainId : order.chainId;
1048
+ const isSolanaOrder = srcChain === import_intents_sdk14.ChainID.Solana;
1049
+ if (isSolanaOrder) {
1050
+ if (!isCrossChain) {
1051
+ const { versionedMessageBytes: versionedMessageBytes2 } = await (0, import_intents_sdk14.cancelSingleChainOrderInstructionsAsBytes)(
1052
+ order.orderId,
1053
+ order.user,
1054
+ { rpcUrl: sol_rpc }
1055
+ );
1056
+ const message2 = import_web32.VersionedMessage.deserialize(
1057
+ versionedMessageBytes2
1058
+ );
1059
+ const tx2 = new import_web32.VersionedTransaction(message2);
1060
+ return await wallet.sendTransaction(tx2);
1061
+ }
1062
+ const { versionedMessageBytes } = await (0, import_intents_sdk14.cancelCrossChainOrderInstructionsAsBytes)(
1063
+ order.orderId,
1064
+ order.user,
1065
+ { rpcUrl: sol_rpc }
1066
+ );
1067
+ const message = import_web32.VersionedMessage.deserialize(
1068
+ versionedMessageBytes
1069
+ );
1070
+ const tx = new import_web32.VersionedTransaction(message);
1071
+ return await wallet.sendTransaction(tx);
1072
+ }
1073
+ const chainId = srcChain;
1074
+ const { readContract } = wallet;
1075
+ if (!readContract) {
1076
+ throw new Error("Wallet does not support readContract");
1077
+ }
1078
+ const nonce = BigInt(order.nonce ?? "0");
1079
+ const nonceWordPos = nonce >> 8n;
1080
+ const nonceBitPos = nonce - nonceWordPos * 256n;
1081
+ if (isCrossChain) {
1082
+ const [orderData = [false, false], currentNonceBitmap = 0n] = await Promise.all([
1083
+ readContract({
1084
+ address: import_intents_sdk14.CROSS_CHAIN_GUARD_ADDRESSES[chainId],
1085
+ abi: [
1086
+ {
1087
+ inputs: [{ name: "orderId", type: "bytes32" }],
1088
+ name: "orderData",
1089
+ outputs: [
1090
+ { name: "initialized", type: "bool" },
1091
+ { name: "deactivated", type: "bool" }
1092
+ ],
1093
+ stateMutability: "view",
1094
+ type: "function"
1095
+ }
1096
+ ],
1097
+ functionName: "orderData",
1098
+ args: [order.orderId]
1099
+ }),
1100
+ readContract({
1101
+ address: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1102
+ abi: [
1103
+ {
1104
+ inputs: [
1105
+ { name: "owner", type: "address" },
1106
+ { name: "wordPos", type: "uint256" }
1107
+ ],
1108
+ name: "nonceBitmap",
1109
+ outputs: [{ name: "", type: "uint256" }],
1110
+ stateMutability: "view",
1111
+ type: "function"
1112
+ }
1113
+ ],
1114
+ functionName: "nonceBitmap",
1115
+ args: [order.user, nonceWordPos]
1116
+ })
1117
+ ]);
1118
+ const [initialized, deactivated] = orderData;
1119
+ if (initialized) {
1120
+ if (deactivated) {
1121
+ throw new Error("Order is already deactivated");
1122
+ }
1123
+ return await wallet.sendTransaction({
1124
+ to: import_intents_sdk14.CROSS_CHAIN_GUARD_ADDRESSES[order.srcChainId],
1125
+ data: (0, import_viem8.encodeFunctionData)({
1126
+ abi: [
1127
+ {
1128
+ inputs: [
1129
+ {
1130
+ components: [
1131
+ { name: "user", type: "address" },
1132
+ { name: "tokenIn", type: "address" },
1133
+ { name: "srcChainId", type: "uint256" },
1134
+ { name: "deadline", type: "uint256" },
1135
+ { name: "amountIn", type: "uint256" },
1136
+ { name: "minStablecoinsAmount", type: "uint256" },
1137
+ { name: "executionDetailsHash", type: "bytes32" },
1138
+ { name: "nonce", type: "uint256" }
1139
+ ],
1140
+ name: "orderInfo",
1141
+ type: "tuple"
1142
+ }
1143
+ ],
1144
+ name: "cancelOrder",
1145
+ outputs: [],
1146
+ stateMutability: "nonpayable",
1147
+ type: "function"
1148
+ }
1149
+ ],
1150
+ functionName: "cancelOrder",
1151
+ args: [
1152
+ {
1153
+ user: order.user,
1154
+ tokenIn: order.tokenIn,
1155
+ srcChainId: BigInt(order.srcChainId),
1156
+ deadline: BigInt(order.deadline),
1157
+ amountIn: BigInt(order.amountIn),
1158
+ minStablecoinsAmount: BigInt(order.minStablecoinsAmount),
1159
+ executionDetailsHash: order.executionDetailsHash,
1160
+ nonce
1161
+ }
1162
+ ]
1163
+ }),
1164
+ value: BigInt(0),
1165
+ from: order.user
1166
+ });
1167
+ } else {
1168
+ if ((currentNonceBitmap & 1n << nonceBitPos) !== 0n) {
1169
+ throw new Error("Nonce is already invalidated");
1170
+ }
1171
+ const mask2 = 1n << nonceBitPos;
1172
+ return await wallet.sendTransaction({
1173
+ to: import_intents_sdk14.PERMIT2_ADDRESS[order.srcChainId],
1174
+ data: (0, import_viem8.encodeFunctionData)({
1175
+ abi: [
1176
+ {
1177
+ inputs: [
1178
+ { name: "wordPos", type: "uint256" },
1179
+ { name: "mask", type: "uint256" }
1180
+ ],
1181
+ name: "invalidateUnorderedNonces",
1182
+ outputs: [],
1183
+ stateMutability: "nonpayable",
1184
+ type: "function"
1185
+ }
1186
+ ],
1187
+ functionName: "invalidateUnorderedNonces",
1188
+ args: [nonceWordPos, mask2]
1189
+ }),
1190
+ value: BigInt(0),
1191
+ from: order.user
1192
+ });
1193
+ }
1194
+ }
1195
+ const [wasManuallyInitialized, currentBitmap = 0n] = await Promise.all([
1196
+ readContract({
1197
+ address: import_intents_sdk14.SINGLE_CHAIN_GUARD_ADDRESSES[chainId],
1198
+ abi: [
1199
+ {
1200
+ inputs: [{ name: "orderHash", type: "bytes32" }],
1201
+ name: "orderManuallyInitialized",
1202
+ outputs: [{ name: "", type: "bool" }],
1203
+ stateMutability: "view",
1204
+ type: "function"
1205
+ }
1206
+ ],
1207
+ functionName: "orderManuallyInitialized",
1208
+ args: [order.orderId]
1209
+ }),
1210
+ readContract({
1211
+ address: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1212
+ abi: [
1213
+ {
1214
+ inputs: [
1215
+ { name: "owner", type: "address" },
1216
+ { name: "wordPos", type: "uint256" }
1217
+ ],
1218
+ name: "nonceBitmap",
1219
+ outputs: [{ name: "", type: "uint256" }],
1220
+ stateMutability: "view",
1221
+ type: "function"
1222
+ }
1223
+ ],
1224
+ functionName: "nonceBitmap",
1225
+ args: [order.user, nonceWordPos]
1226
+ })
1227
+ ]);
1228
+ if (wasManuallyInitialized) {
1229
+ return await wallet.sendTransaction({
1230
+ to: import_intents_sdk14.SINGLE_CHAIN_GUARD_ADDRESSES[chainId],
1231
+ data: (0, import_viem8.encodeFunctionData)({
1232
+ abi: [
1233
+ {
1234
+ inputs: [
1235
+ {
1236
+ name: "order",
1237
+ type: "tuple",
1238
+ components: [
1239
+ { name: "amountIn", type: "uint256" },
1240
+ { name: "tokenIn", type: "address" },
1241
+ { name: "deadline", type: "uint256" },
1242
+ { name: "nonce", type: "uint256" },
1243
+ { name: "encodedExternalCallData", type: "bytes" },
1244
+ {
1245
+ name: "extraTransfers",
1246
+ type: "tuple[]",
1247
+ components: [
1248
+ { name: "amount", type: "uint256" },
1249
+ { name: "receiver", type: "address" },
1250
+ { name: "token", type: "address" }
1251
+ ]
1252
+ },
1253
+ {
1254
+ name: "requestedOutput",
1255
+ type: "tuple",
1256
+ components: [
1257
+ { name: "amount", type: "uint256" },
1258
+ { name: "receiver", type: "address" },
1259
+ { name: "token", type: "address" }
1260
+ ]
1261
+ },
1262
+ { name: "user", type: "address" }
1263
+ ]
1264
+ }
1265
+ ],
1266
+ name: "cancelManuallyCreatedOrder",
1267
+ outputs: [],
1268
+ stateMutability: "nonpayable",
1269
+ type: "function"
1270
+ }
1271
+ ],
1272
+ functionName: "cancelManuallyCreatedOrder",
1273
+ args: [
1274
+ {
1275
+ amountIn: BigInt(order.amountIn),
1276
+ tokenIn: order.tokenIn,
1277
+ deadline: BigInt(order.deadline),
1278
+ nonce,
1279
+ encodedExternalCallData: "0x",
1280
+ extraTransfers: (order.extraTransfers || []).map((t) => ({
1281
+ amount: BigInt(t.amount),
1282
+ receiver: t.receiver,
1283
+ token: t.token
1284
+ })),
1285
+ requestedOutput: {
1286
+ amount: BigInt(order.amountOutMin),
1287
+ receiver: order.destinationAddress,
1288
+ token: order.tokenOut
1289
+ },
1290
+ user: order.user
1291
+ }
1292
+ ]
1293
+ }),
1294
+ value: 0n,
1295
+ from: order.user
1296
+ });
1297
+ }
1298
+ const mask = 1n << nonceBitPos;
1299
+ if ((currentBitmap & mask) !== 0n) {
1300
+ throw new Error("Nonce is already invalidated");
1301
+ }
1302
+ return await wallet.sendTransaction({
1303
+ to: import_intents_sdk14.PERMIT2_ADDRESS[chainId],
1304
+ data: (0, import_viem8.encodeFunctionData)({
1305
+ abi: [
1306
+ {
1307
+ inputs: [
1308
+ { name: "wordPos", type: "uint256" },
1309
+ { name: "mask", type: "uint256" }
1310
+ ],
1311
+ name: "invalidateUnorderedNonces",
1312
+ outputs: [],
1313
+ stateMutability: "nonpayable",
1314
+ type: "function"
1315
+ }
1316
+ ],
1317
+ functionName: "invalidateUnorderedNonces",
1318
+ args: [nonceWordPos, mask]
1319
+ }),
1320
+ value: 0n,
1321
+ from: order.user
1322
+ });
1323
+ }
1324
+
1325
+ // src/core/client.ts
1326
+ var SwapSDK = class {
1327
+ constructor(config) {
1328
+ __publicField(this, "apiKey");
1329
+ /**
1330
+ * Fetches metadata for one or more tokens from the Shogun Token Search API.
1331
+ *
1332
+ * ---
1333
+ * ### Overview
1334
+ * `getTokensData` retrieves normalized token information — such as symbol, name,
1335
+ * decimals, logo URI, and verified status — for a given list of token addresses.
1336
+ *
1337
+ * It supports both **EVM** and **SVM (Solana)** tokens, returning metadata from
1338
+ * Shogun’s unified token registry.
1339
+ *
1340
+ * ---
1341
+ * @example
1342
+ * ```ts
1343
+ * const tokens = await getTokensData([
1344
+ * "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
1345
+ * "So11111111111111111111111111111111111111112", // SOL
1346
+ * ]);
1347
+ *
1348
+ * console.log(tokens);
1349
+ * [
1350
+ * { symbol: "USDC", name: "USD Coin", chainId: 1, decimals: 6, ... },
1351
+ * { symbol: "SOL", name: "Solana", chainId: 101, decimals: 9, ... }
1352
+ * ]
1353
+ * ```
1354
+ *
1355
+ * @param addresses - An array of token addresses (EVM or SVM) to fetch metadata for.
1356
+ * @returns A promise resolving to an array of {@link TokenInfo} objects.
1357
+ *
1358
+ * @throws Will throw an error if the network request fails or the API responds with a non-OK status.
1359
+ */
1360
+ __publicField(this, "getTokensData", getTokensData.bind(this));
1361
+ if (!config.apiKey) {
1362
+ throw new Error("SwapSDK: Missing API key");
1363
+ }
1364
+ this.apiKey = config.apiKey;
1365
+ if (this.apiKey) void this.apiKey;
1366
+ }
1367
+ /**
1368
+ * Retrieves a swap quote for the given input and output tokens.
1369
+ *
1370
+ * @param params - Quote parameters including source/destination tokens and amount.
1371
+ * @returns A normalized `SwapQuoteResponse` containing output amount, route, and metadata.
1372
+ */
1373
+ async getQuote(params) {
1374
+ return getQuote(params);
1375
+ }
1376
+ /**
1377
+ * Fetches token balances for the specified user wallet(s).
1378
+ *
1379
+ * Supports both EVM and SVM (Solana) wallet addresses.
1380
+ *
1381
+ * @param params - Wallet address and optional chain filters.
1382
+ * @param options - Optional abort signal for cancellation.
1383
+ * @returns A unified balance response with per-chain token details.
1384
+ */
1385
+ async getBalances(params, options) {
1386
+ return getBalances(params, options);
1387
+ }
1388
+ /**
1389
+ * Retrieves a list of verified tokens based on search query or chain filter.
1390
+ *
1391
+ * @param params - Search parameters (query, chain ID, pagination options).
1392
+ * @returns Paginated `TokenSearchResponse` containing token metadata.
1393
+ */
1394
+ async getTokenList(params) {
1395
+ return getTokenList(params);
1396
+ }
1397
+ /**
1398
+ * Executes a prepared swap quote using the provided wallet and configuration.
1399
+ *
1400
+ * Handles:
1401
+ * - Token approval (if required)
1402
+ * - Transaction signing and broadcasting
1403
+ * - Confirmation polling and stage-based status updates
1404
+ *
1405
+ * Supports both:
1406
+ * - Market orders (with optional deadline)
1407
+ * - Limit orders (requires executionPrice and deadline)
1408
+ *
1409
+ * @param quote - The swap quote to execute, containing route and metadata.
1410
+ * @param accountAddress - The user's wallet address executing the swap.
1411
+ * @param recipientAddress - Optional recipient address for the output tokens (defaults to sender).
1412
+ * @param wallet - Adapted wallet instance (EVM/Solana) or a standard Viem `WalletClient`.
1413
+ * @param onStatus - Optional callback for receiving execution stage updates and messages.
1414
+ * @param orderType - Defines whether this is a market or limit order.
1415
+ * @param options - Execution parameters (different per order type).
1416
+ *
1417
+ * @returns A finalized execution result containing transaction hash, status, and any returned data.
1418
+ *
1419
+ * @example
1420
+ * ```ts
1421
+ * * Market order
1422
+ * const result = await sdk.executeTransaction({
1423
+ * quote,
1424
+ * accountAddress: "0x123...",
1425
+ * wallet,
1426
+ * orderType: OrderExecutionType.MARKET,
1427
+ * options: { deadline: 1800 },
1428
+ * onStatus: (stage, msg) => console.log(stage, msg),
1429
+ * });
1430
+ *
1431
+ * * Limit order
1432
+ * const result = await sdk.executeTransaction({
1433
+ * quote,
1434
+ * accountAddress: "0x123...",
1435
+ * wallet,
1436
+ * orderType: OrderExecutionType.LIMIT,
1437
+ * options: { executionPrice: "0.0021", deadline: 3600 },
1438
+ * });
1439
+ * ```
1440
+ */
1441
+ async executeTransaction({
1442
+ quote,
1443
+ accountAddress,
1444
+ recipientAddress,
1445
+ wallet,
1446
+ onStatus,
1447
+ orderType,
1448
+ options
1449
+ }) {
1450
+ return executeOrder({
1451
+ quote,
1452
+ wallet,
1453
+ accountAddress,
1454
+ recipientAddress,
1455
+ onStatus,
1456
+ orderType,
1457
+ options
1458
+ });
1459
+ }
1460
+ /**
1461
+ * Fetches all user orders (Market, Limit, Cross-chain) for connected wallets.
1462
+ *
1463
+ * ---
1464
+ * ### Overview
1465
+ * Retrieves both **single-chain** and **cross-chain** orders from the Shogun Intents API.
1466
+ * Works across EVM, Solana
1467
+ *
1468
+ * ---
1469
+ * @example
1470
+ * ```ts
1471
+ * const orders = await sdk.getOrders({
1472
+ * evmAddress: "0x123...",
1473
+ * solAddress: "9d12hF...abc",
1474
+ * });
1475
+ *
1476
+ * console.log(orders.singleChainLimitOrders);
1477
+ * ```
1478
+ *
1479
+ * @param params - Wallet addresses to fetch orders for (EVM, Solana).
1480
+ * @returns A structured {@link ApiUserOrders} object containing all user orders.
1481
+ */
1482
+ async getOrders(params) {
1483
+ return getOrders(params);
1484
+ }
1485
+ /**
1486
+ * Cancels an order (single-chain or cross-chain) on EVM or Solana.
1487
+ *
1488
+ * Internally routes to the correct guard contract or Solana program to
1489
+ * deactivate the order or invalidate its nonce.
1490
+ *
1491
+ * @param params.order - Order payload returned from the Intents API.
1492
+ * @param params.wallet - Adapted wallet used to submit the cancellation transaction.
1493
+ * @param params.solRpc - Solana RPC URL used for SVM cancellations.
1494
+ *
1495
+ * @returns A transaction signature or hash from the underlying wallet.
1496
+ */
1497
+ async cancelOrder(params) {
1498
+ return cancelIntentsOrder({
1499
+ order: params.order,
1500
+ wallet: params.wallet,
1501
+ sol_rpc: params.solRpc
1502
+ });
1503
+ }
1504
+ };