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