@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/core.cjs +408 -110
- package/dist/core.d.cts +4 -137
- package/dist/core.d.ts +4 -137
- package/dist/core.js +386 -86
- package/dist/index-CmsKzdEu.d.cts +377 -0
- package/dist/index-Qoc6Q9XN.d.ts +377 -0
- package/dist/index.cjs +401 -497
- package/dist/index.d.cts +4 -9
- package/dist/index.d.ts +4 -9
- package/dist/index.js +379 -475
- package/dist/react.cjs +924 -469
- package/dist/react.d.cts +258 -82
- package/dist/react.d.ts +258 -82
- package/dist/react.js +890 -443
- package/dist/{wallet-BhuMJ3K_.d.cts → wallet-B9bKceyN.d.cts} +1 -2
- package/dist/{wallet-BhuMJ3K_.d.ts → wallet-B9bKceyN.d.ts} +1 -2
- package/dist/wallet-adapter.cjs +25607 -11
- package/dist/wallet-adapter.d.cts +1 -2
- package/dist/wallet-adapter.d.ts +1 -2
- package/dist/wallet-adapter.js +25626 -6
- package/package.json +44 -14
- package/dist/execute-D2qcOzkI.d.ts +0 -145
- package/dist/execute-Xvw4wXBo.d.cts +0 -145
package/dist/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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/
|
|
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 =
|
|
34
|
-
var
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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/
|
|
133
|
+
// src/core/execute/normalizeNative.ts
|
|
118
134
|
function normalizeNative(chainId, address) {
|
|
119
|
-
if (
|
|
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 (
|
|
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
|
|
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:
|
|
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/
|
|
255
|
-
import {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
|
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:
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
-
|
|
661
|
-
|
|
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
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
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/
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 {
|
|
786
|
+
const { intentId: orderId } = response.data;
|
|
777
787
|
update("initiated", messageFor("shogun_processing"));
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
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/
|
|
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 (
|
|
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
|
-
|
|
861
|
-
|
|
892
|
+
update,
|
|
893
|
+
orderType,
|
|
894
|
+
options
|
|
862
895
|
});
|
|
863
896
|
log("EVM execution result:", result);
|
|
864
897
|
return result;
|
|
865
898
|
}
|
|
866
|
-
if (chainId ===
|
|
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
|
-
|
|
875
|
-
|
|
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
|
-
|
|
886
|
-
|
|
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/
|
|
898
|
-
import {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
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
|
-
|
|
938
|
-
|
|
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/
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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
|
-
|
|
988
|
-
|
|
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
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
-
|
|
1195
|
-
|
|
1111
|
+
ChainId,
|
|
1112
|
+
OrderExecutionType,
|
|
1196
1113
|
SupportedChains,
|
|
1197
|
-
|
|
1198
|
-
adaptSolanaWallet,
|
|
1199
|
-
adaptViemWallet,
|
|
1114
|
+
SwapSDK,
|
|
1200
1115
|
buildQuoteParams,
|
|
1201
|
-
|
|
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
|
};
|