@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.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,44 +17,26 @@ 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/index.ts
|
|
21
23
|
var src_exports = {};
|
|
22
24
|
__export(src_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
ChainId: () => ChainId,
|
|
26
|
+
OrderExecutionType: () => OrderExecutionType,
|
|
25
27
|
SupportedChains: () => SupportedChains,
|
|
26
|
-
|
|
27
|
-
adaptSolanaWallet: () => adaptSolanaWallet,
|
|
28
|
-
adaptViemWallet: () => adaptViemWallet,
|
|
28
|
+
SwapSDK: () => SwapSDK,
|
|
29
29
|
buildQuoteParams: () => buildQuoteParams,
|
|
30
|
-
|
|
31
|
-
getBalances: () => getBalances,
|
|
32
|
-
getQuote: () => getQuote,
|
|
33
|
-
getTokenList: () => getTokenList,
|
|
34
|
-
isNativeAddress: () => isNativeAddress,
|
|
35
|
-
isViemWalletClient: () => isViemWalletClient,
|
|
36
|
-
normalizeEvmTokenAddress: () => normalizeEvmTokenAddress,
|
|
37
|
-
serializeBigIntsToStrings: () => serializeBigIntsToStrings,
|
|
38
|
-
useBalances: () => useBalances,
|
|
39
|
-
useExecuteOrder: () => useExecuteOrder,
|
|
40
|
-
useQuote: () => useQuote,
|
|
41
|
-
useTokenList: () => useTokenList
|
|
30
|
+
isEvmChain: () => isEvmChain
|
|
42
31
|
});
|
|
43
32
|
module.exports = __toCommonJS(src_exports);
|
|
44
33
|
|
|
45
|
-
// src/core/token-list.ts
|
|
46
|
-
var import_intents_sdk = require("@shogun-sdk/intents-sdk");
|
|
47
|
-
async function getTokenList(params) {
|
|
48
|
-
return (0, import_intents_sdk.getTokenList)(params);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
34
|
// src/core/getQuote.ts
|
|
52
|
-
var
|
|
35
|
+
var import_intents_sdk3 = require("@shogun-sdk/intents-sdk");
|
|
53
36
|
var import_viem2 = require("viem");
|
|
54
37
|
|
|
55
|
-
// src/core/
|
|
56
|
-
var
|
|
38
|
+
// src/core/execute/normalizeNative.ts
|
|
39
|
+
var import_intents_sdk2 = require("@shogun-sdk/intents-sdk");
|
|
57
40
|
|
|
58
41
|
// src/utils/address.ts
|
|
59
42
|
var import_viem = require("viem");
|
|
@@ -73,11 +56,25 @@ function normalizeEvmTokenAddress(address) {
|
|
|
73
56
|
}
|
|
74
57
|
|
|
75
58
|
// src/utils/chain.ts
|
|
76
|
-
var
|
|
77
|
-
var SOLANA_CHAIN_ID =
|
|
78
|
-
var
|
|
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
|
+
];
|
|
66
|
+
var ChainId = Object.entries(import_intents_sdk.ChainID).reduce(
|
|
67
|
+
(acc, [key, value]) => {
|
|
68
|
+
if (typeof value === "number" && CURRENT_SUPPORTED.includes(value)) {
|
|
69
|
+
acc[key] = value;
|
|
70
|
+
}
|
|
71
|
+
return acc;
|
|
72
|
+
},
|
|
73
|
+
{}
|
|
74
|
+
);
|
|
75
|
+
var SupportedChainsInternal = [
|
|
79
76
|
{
|
|
80
|
-
id:
|
|
77
|
+
id: import_intents_sdk.ChainID.Arbitrum,
|
|
81
78
|
name: "Arbitrum",
|
|
82
79
|
isEVM: true,
|
|
83
80
|
wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
@@ -86,7 +83,7 @@ var SupportedChains = [
|
|
|
86
83
|
tokenAddress: NATIVE_TOKEN.ETH
|
|
87
84
|
},
|
|
88
85
|
{
|
|
89
|
-
id:
|
|
86
|
+
id: import_intents_sdk.ChainID.Optimism,
|
|
90
87
|
name: "Optimism",
|
|
91
88
|
isEVM: true,
|
|
92
89
|
wrapped: "0x4200000000000000000000000000000000000006",
|
|
@@ -95,7 +92,7 @@ var SupportedChains = [
|
|
|
95
92
|
tokenAddress: NATIVE_TOKEN.ETH
|
|
96
93
|
},
|
|
97
94
|
{
|
|
98
|
-
id:
|
|
95
|
+
id: import_intents_sdk.ChainID.Base,
|
|
99
96
|
name: "Base",
|
|
100
97
|
isEVM: true,
|
|
101
98
|
wrapped: "0x4200000000000000000000000000000000000006",
|
|
@@ -104,7 +101,7 @@ var SupportedChains = [
|
|
|
104
101
|
tokenAddress: NATIVE_TOKEN.ETH
|
|
105
102
|
},
|
|
106
103
|
{
|
|
107
|
-
id:
|
|
104
|
+
id: import_intents_sdk.ChainID.Hyperliquid,
|
|
108
105
|
name: "Hyperliquid",
|
|
109
106
|
isEVM: true,
|
|
110
107
|
wrapped: "0x5555555555555555555555555555555555555555",
|
|
@@ -113,7 +110,7 @@ var SupportedChains = [
|
|
|
113
110
|
tokenAddress: NATIVE_TOKEN.ETH
|
|
114
111
|
},
|
|
115
112
|
{
|
|
116
|
-
id:
|
|
113
|
+
id: import_intents_sdk.ChainID.BSC,
|
|
117
114
|
name: "BSC",
|
|
118
115
|
isEVM: true,
|
|
119
116
|
wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
@@ -131,6 +128,10 @@ var SupportedChains = [
|
|
|
131
128
|
tokenAddress: NATIVE_TOKEN.SOL
|
|
132
129
|
}
|
|
133
130
|
];
|
|
131
|
+
var SupportedChains = SupportedChainsInternal.filter(
|
|
132
|
+
(c) => CURRENT_SUPPORTED.includes(c.id)
|
|
133
|
+
);
|
|
134
|
+
var isEvmChain = import_intents_sdk.isEvmChain;
|
|
134
135
|
|
|
135
136
|
// src/utils/viem.ts
|
|
136
137
|
function isViemWalletClient(wallet) {
|
|
@@ -158,9 +159,9 @@ function serializeBigIntsToStrings(obj) {
|
|
|
158
159
|
return obj;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
// src/core/
|
|
162
|
+
// src/core/execute/normalizeNative.ts
|
|
162
163
|
function normalizeNative(chainId, address) {
|
|
163
|
-
if ((0,
|
|
164
|
+
if ((0, import_intents_sdk2.isEvmChain)(chainId) && isNativeAddress(address)) {
|
|
164
165
|
const chain = SupportedChains.find((c) => c.id === chainId);
|
|
165
166
|
if (!chain?.wrapped)
|
|
166
167
|
throw new Error(`Wrapped token not found for chainId ${chainId}`);
|
|
@@ -171,22 +172,23 @@ function normalizeNative(chainId, address) {
|
|
|
171
172
|
|
|
172
173
|
// src/core/getQuote.ts
|
|
173
174
|
async function getQuote(params) {
|
|
175
|
+
const amount = BigInt(params.amount);
|
|
174
176
|
if (!params.tokenIn?.address || !params.tokenOut?.address) {
|
|
175
177
|
throw new Error("Both tokenIn and tokenOut must include an address.");
|
|
176
178
|
}
|
|
177
179
|
if (!params.sourceChainId || !params.destChainId) {
|
|
178
180
|
throw new Error("Both sourceChainId and destChainId are required.");
|
|
179
181
|
}
|
|
180
|
-
if (
|
|
182
|
+
if (amount <= 0n) {
|
|
181
183
|
throw new Error("Amount must be greater than 0.");
|
|
182
184
|
}
|
|
183
185
|
const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
|
|
184
|
-
const data = await
|
|
186
|
+
const data = await import_intents_sdk3.QuoteProvider.getQuote({
|
|
185
187
|
sourceChainId: params.sourceChainId,
|
|
186
188
|
destChainId: params.destChainId,
|
|
187
189
|
tokenIn: normalizedTokenIn,
|
|
188
190
|
tokenOut: params.tokenOut.address,
|
|
189
|
-
amount
|
|
191
|
+
amount
|
|
190
192
|
});
|
|
191
193
|
const slippagePercent = Math.min(Math.max(params.slippage ?? 0.5, 0), 50);
|
|
192
194
|
let warning;
|
|
@@ -217,7 +219,7 @@ async function getQuote(params) {
|
|
|
217
219
|
decimals: params.tokenOut.decimals ?? 18,
|
|
218
220
|
chainId: params.destChainId
|
|
219
221
|
},
|
|
220
|
-
amountIn: params.amount,
|
|
222
|
+
amountIn: BigInt(params.amount),
|
|
221
223
|
pricePerInputToken,
|
|
222
224
|
slippage: slippagePercent,
|
|
223
225
|
internal: {
|
|
@@ -241,13 +243,13 @@ function buildQuoteParams({
|
|
|
241
243
|
tokenOut,
|
|
242
244
|
sourceChainId,
|
|
243
245
|
destChainId,
|
|
244
|
-
amount: (0, import_viem2.parseUnits)(amount.toString(), tokenIn.decimals ?? 18),
|
|
246
|
+
amount: (0, import_viem2.parseUnits)(amount.toString(), tokenIn.decimals ?? 18).toString(),
|
|
245
247
|
slippage
|
|
246
248
|
};
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
// src/core/getBalances.ts
|
|
250
|
-
var
|
|
252
|
+
var import_intents_sdk4 = require("@shogun-sdk/intents-sdk");
|
|
251
253
|
async function getBalances(params, options) {
|
|
252
254
|
const { addresses, cursorEvm, cursorSvm } = params;
|
|
253
255
|
const { signal } = options ?? {};
|
|
@@ -260,7 +262,7 @@ async function getBalances(params, options) {
|
|
|
260
262
|
cursorSvm
|
|
261
263
|
});
|
|
262
264
|
const start = performance.now();
|
|
263
|
-
const response = await fetch(`${
|
|
265
|
+
const response = await fetch(`${import_intents_sdk4.TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
|
|
264
266
|
method: "POST",
|
|
265
267
|
headers: {
|
|
266
268
|
accept: "application/json",
|
|
@@ -288,119 +290,70 @@ async function getBalances(params, options) {
|
|
|
288
290
|
const evmItems = data.evm?.items ?? [];
|
|
289
291
|
const svmItems = data.svm?.items ?? [];
|
|
290
292
|
const combined = [...evmItems, ...svmItems];
|
|
293
|
+
const filtered = combined.filter(
|
|
294
|
+
(b) => CURRENT_SUPPORTED.includes(b.chainId)
|
|
295
|
+
);
|
|
291
296
|
return {
|
|
292
|
-
results:
|
|
297
|
+
results: filtered,
|
|
293
298
|
nextCursorEvm: data.evm?.cursor ?? null,
|
|
294
299
|
nextCursorSvm: data.svm?.cursor ?? null
|
|
295
300
|
};
|
|
296
301
|
}
|
|
297
302
|
|
|
298
|
-
// src/core/
|
|
299
|
-
var
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return txHash;
|
|
317
|
-
}
|
|
318
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
319
|
-
}
|
|
320
|
-
throw new Error(`Transaction not confirmed after ${maxRetries * (delayMs / 1e3)}s`);
|
|
321
|
-
};
|
|
322
|
-
const signTypedData = async () => {
|
|
323
|
-
throw new Error("signTypedData not implemented for Solana");
|
|
324
|
-
};
|
|
325
|
-
const switchChain = async (newChainId) => {
|
|
326
|
-
_chainId = newChainId;
|
|
327
|
-
};
|
|
303
|
+
// src/core/token-list.ts
|
|
304
|
+
var import_intents_sdk5 = require("@shogun-sdk/intents-sdk");
|
|
305
|
+
async function getTokenList(params) {
|
|
306
|
+
const url = new URL(`${import_intents_sdk5.TOKEN_SEARCH_API_BASE_URL}/tokens/search`);
|
|
307
|
+
if (params.q) url.searchParams.append("q", params.q);
|
|
308
|
+
if (params.networkId) url.searchParams.append("networkId", String(params.networkId));
|
|
309
|
+
if (params.page) url.searchParams.append("page", String(params.page));
|
|
310
|
+
if (params.limit) url.searchParams.append("limit", String(params.limit));
|
|
311
|
+
const res = await fetch(url.toString(), {
|
|
312
|
+
signal: params.signal
|
|
313
|
+
});
|
|
314
|
+
if (!res.ok) {
|
|
315
|
+
throw new Error(`Failed to fetch tokens: ${res.status} ${res.statusText}`);
|
|
316
|
+
}
|
|
317
|
+
const data = await res.json();
|
|
318
|
+
const filteredResults = data.results.filter(
|
|
319
|
+
(token) => CURRENT_SUPPORTED.includes(token.chainId)
|
|
320
|
+
);
|
|
328
321
|
return {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
sendTransaction,
|
|
333
|
-
switchChain,
|
|
334
|
-
signTypedData,
|
|
335
|
-
rpcUrl
|
|
322
|
+
...data,
|
|
323
|
+
results: filteredResults,
|
|
324
|
+
count: filteredResults.length
|
|
336
325
|
};
|
|
337
|
-
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/core/token.ts
|
|
329
|
+
var import_intents_sdk6 = require("@shogun-sdk/intents-sdk");
|
|
330
|
+
async function getTokensData(addresses) {
|
|
331
|
+
if (!addresses?.length) return [];
|
|
332
|
+
const response = await fetch(`${import_intents_sdk6.TOKEN_SEARCH_API_BASE_URL}/tokens/tokens`, {
|
|
333
|
+
method: "POST",
|
|
334
|
+
headers: {
|
|
335
|
+
"Content-Type": "application/json",
|
|
336
|
+
accept: "*/*"
|
|
337
|
+
},
|
|
338
|
+
body: JSON.stringify({ addresses })
|
|
339
|
+
});
|
|
340
|
+
if (!response.ok) {
|
|
341
|
+
throw new Error(`Failed to fetch token data: ${response.statusText}`);
|
|
342
|
+
}
|
|
343
|
+
const data = await response.json();
|
|
344
|
+
const filtered = data.filter((t) => CURRENT_SUPPORTED.includes(Number(t.chainId)));
|
|
345
|
+
return filtered;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/core/execute/execute.ts
|
|
349
|
+
var import_intents_sdk12 = require("@shogun-sdk/intents-sdk");
|
|
350
|
+
var import_viem7 = require("viem");
|
|
338
351
|
|
|
339
352
|
// src/wallet-adapter/evm-wallet-adapter/adapter.ts
|
|
340
|
-
var import_ethers = require("ethers/lib/ethers.js");
|
|
341
|
-
var import_utils2 = require("ethers/lib/utils.js");
|
|
342
353
|
var import_viem3 = require("viem");
|
|
343
354
|
function isEVMTransaction(tx) {
|
|
344
355
|
return typeof tx.from === "string";
|
|
345
356
|
}
|
|
346
|
-
var adaptEthersSigner = (signer, transport) => {
|
|
347
|
-
const signTypedData = async (signData) => {
|
|
348
|
-
const typedSigner = signer;
|
|
349
|
-
return await typedSigner._signTypedData(
|
|
350
|
-
signData.domain,
|
|
351
|
-
signData.types,
|
|
352
|
-
signData.value
|
|
353
|
-
);
|
|
354
|
-
};
|
|
355
|
-
const sendTransaction = async (transaction) => {
|
|
356
|
-
if (!isEVMTransaction(transaction)) {
|
|
357
|
-
throw new Error("Expected EVMTransaction but got SolanaTransaction");
|
|
358
|
-
}
|
|
359
|
-
const tx = await signer.sendTransaction({
|
|
360
|
-
from: transaction.from,
|
|
361
|
-
to: transaction.to,
|
|
362
|
-
data: transaction.data,
|
|
363
|
-
value: transaction.value
|
|
364
|
-
});
|
|
365
|
-
return tx.hash;
|
|
366
|
-
};
|
|
367
|
-
const switchChain = async (chainId) => {
|
|
368
|
-
try {
|
|
369
|
-
await window.ethereum.request({
|
|
370
|
-
method: "wallet_switchEthereumChain",
|
|
371
|
-
params: [{ chainId: (0, import_utils2.hexValue)(chainId) }]
|
|
372
|
-
});
|
|
373
|
-
} catch (error) {
|
|
374
|
-
console.error("Failed to switch chain:", error);
|
|
375
|
-
throw error;
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
const readContract = async ({
|
|
379
|
-
address,
|
|
380
|
-
abi,
|
|
381
|
-
functionName,
|
|
382
|
-
args = []
|
|
383
|
-
}) => {
|
|
384
|
-
const iface = new import_ethers.utils.Interface(abi);
|
|
385
|
-
const fnArgs = Array.isArray(args) ? args : [];
|
|
386
|
-
const data = iface.encodeFunctionData(functionName, fnArgs);
|
|
387
|
-
const provider = signer.provider;
|
|
388
|
-
if (!provider) throw new Error("Signer has no provider");
|
|
389
|
-
const result = await provider.call({ to: address, data });
|
|
390
|
-
const decoded = iface.decodeFunctionResult(functionName, result);
|
|
391
|
-
return decoded[0];
|
|
392
|
-
};
|
|
393
|
-
return {
|
|
394
|
-
vmType: "EVM" /* EVM */,
|
|
395
|
-
transport,
|
|
396
|
-
getChainId: async () => signer.getChainId(),
|
|
397
|
-
address: async () => signer.getAddress(),
|
|
398
|
-
sendTransaction,
|
|
399
|
-
signTypedData,
|
|
400
|
-
switchChain,
|
|
401
|
-
readContract
|
|
402
|
-
};
|
|
403
|
-
};
|
|
404
357
|
var adaptViemWallet = (wallet) => {
|
|
405
358
|
const signTypedData = async (signData) => {
|
|
406
359
|
return await wallet.signTypedData({
|
|
@@ -483,11 +436,11 @@ var adaptViemWallet = (wallet) => {
|
|
|
483
436
|
};
|
|
484
437
|
};
|
|
485
438
|
|
|
486
|
-
// src/core/
|
|
487
|
-
var
|
|
488
|
-
var
|
|
439
|
+
// src/core/execute/handleEvmExecution.ts
|
|
440
|
+
var import_intents_sdk10 = require("@shogun-sdk/intents-sdk");
|
|
441
|
+
var import_viem6 = require("viem");
|
|
489
442
|
|
|
490
|
-
// src/core/
|
|
443
|
+
// src/core/execute/stageMessages.ts
|
|
491
444
|
var DEFAULT_STAGE_MESSAGES = {
|
|
492
445
|
processing: "Preparing transaction for execution",
|
|
493
446
|
approving: "Approving token allowance",
|
|
@@ -496,33 +449,57 @@ var DEFAULT_STAGE_MESSAGES = {
|
|
|
496
449
|
submitting: "Submitting transaction",
|
|
497
450
|
initiated: "Transaction initiated.",
|
|
498
451
|
success: "Transaction Executed successfully",
|
|
452
|
+
success_limit: "Limit order has been submitted successfully.",
|
|
499
453
|
shogun_processing: "Shogun is processing your transaction",
|
|
500
454
|
error: "Transaction failed during submission"
|
|
501
455
|
};
|
|
502
456
|
|
|
503
|
-
// src/core/
|
|
504
|
-
var
|
|
457
|
+
// src/core/execute/buildOrder.ts
|
|
458
|
+
var import_intents_sdk7 = require("@shogun-sdk/intents-sdk");
|
|
459
|
+
var import_viem4 = require("viem");
|
|
460
|
+
|
|
461
|
+
// src/utils/order.ts
|
|
462
|
+
var OrderExecutionType = /* @__PURE__ */ ((OrderExecutionType2) => {
|
|
463
|
+
OrderExecutionType2["LIMIT"] = "limit";
|
|
464
|
+
OrderExecutionType2["MARKET"] = "market";
|
|
465
|
+
return OrderExecutionType2;
|
|
466
|
+
})(OrderExecutionType || {});
|
|
467
|
+
|
|
468
|
+
// src/core/execute/buildOrder.ts
|
|
505
469
|
async function buildOrder({
|
|
506
470
|
quote,
|
|
507
471
|
accountAddress,
|
|
508
472
|
destination,
|
|
509
473
|
deadline,
|
|
510
|
-
isSingleChain
|
|
474
|
+
isSingleChain,
|
|
475
|
+
orderType,
|
|
476
|
+
options
|
|
511
477
|
}) {
|
|
512
478
|
const { tokenIn, tokenOut } = quote;
|
|
479
|
+
let amountOutMin = BigInt(quote.internal.estimatedAmountOutReduced);
|
|
480
|
+
if (orderType === "limit" /* LIMIT */ && options && "executionPrice" in options) {
|
|
481
|
+
const executionPrice = Number(options.executionPrice);
|
|
482
|
+
if (Number.isFinite(executionPrice) && executionPrice > 0) {
|
|
483
|
+
const decimalsIn = tokenIn.decimals ?? 18;
|
|
484
|
+
const decimalsOut = tokenOut.decimals ?? 18;
|
|
485
|
+
const formattedAmountIn = Number((0, import_viem4.formatUnits)(BigInt(quote.amountIn.toString()), decimalsIn));
|
|
486
|
+
const rawAmountOut = formattedAmountIn * executionPrice;
|
|
487
|
+
amountOutMin = (0, import_viem4.parseUnits)(rawAmountOut.toString(), decimalsOut);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
513
490
|
if (isSingleChain) {
|
|
514
|
-
return await
|
|
491
|
+
return await import_intents_sdk7.SingleChainOrder.create({
|
|
515
492
|
user: accountAddress,
|
|
516
493
|
chainId: tokenIn.chainId,
|
|
517
494
|
tokenIn: tokenIn.address,
|
|
518
495
|
tokenOut: tokenOut.address,
|
|
519
496
|
amountIn: quote.amountIn,
|
|
520
|
-
amountOutMin
|
|
497
|
+
amountOutMin,
|
|
521
498
|
deadline,
|
|
522
499
|
destinationAddress: destination
|
|
523
500
|
});
|
|
524
501
|
}
|
|
525
|
-
return await
|
|
502
|
+
return await import_intents_sdk7.CrossChainOrder.create({
|
|
526
503
|
user: accountAddress,
|
|
527
504
|
sourceChainId: tokenIn.chainId,
|
|
528
505
|
sourceTokenAddress: tokenIn.address,
|
|
@@ -531,13 +508,13 @@ async function buildOrder({
|
|
|
531
508
|
destinationTokenAddress: tokenOut.address,
|
|
532
509
|
destinationAddress: destination,
|
|
533
510
|
deadline,
|
|
534
|
-
destinationTokenMinAmount:
|
|
511
|
+
destinationTokenMinAmount: amountOutMin,
|
|
535
512
|
minStablecoinAmount: quote.minStablecoinsAmount
|
|
536
513
|
});
|
|
537
514
|
}
|
|
538
515
|
|
|
539
516
|
// src/utils/pollOrderStatus.ts
|
|
540
|
-
var
|
|
517
|
+
var import_intents_sdk8 = require("@shogun-sdk/intents-sdk");
|
|
541
518
|
async function pollOrderStatus(address, orderId, options = {}) {
|
|
542
519
|
const { intervalMs = 2e3, timeoutMs = 3e5 } = options;
|
|
543
520
|
const startTime = Date.now();
|
|
@@ -550,7 +527,7 @@ async function pollOrderStatus(address, orderId, options = {}) {
|
|
|
550
527
|
else if (isSuiAddress) queryParam = `suiWallets=${address}`;
|
|
551
528
|
else if (isSolanaAddress) queryParam = `solanaWallets=${address}`;
|
|
552
529
|
else throw new Error(`Unrecognized wallet address format: ${address}`);
|
|
553
|
-
const queryUrl = `${
|
|
530
|
+
const queryUrl = `${import_intents_sdk8.AUCTIONEER_URL}/user_intent?${queryParam}`;
|
|
554
531
|
return new Promise((resolve, reject) => {
|
|
555
532
|
const pollInterval = setInterval(async () => {
|
|
556
533
|
try {
|
|
@@ -602,7 +579,7 @@ async function pollOrderStatus(address, orderId, options = {}) {
|
|
|
602
579
|
});
|
|
603
580
|
}
|
|
604
581
|
|
|
605
|
-
// src/core/
|
|
582
|
+
// src/core/execute/handleOrderPollingResult.ts
|
|
606
583
|
async function handleOrderPollingResult({
|
|
607
584
|
status,
|
|
608
585
|
orderId,
|
|
@@ -640,9 +617,9 @@ async function handleOrderPollingResult({
|
|
|
640
617
|
};
|
|
641
618
|
}
|
|
642
619
|
|
|
643
|
-
// src/core/
|
|
644
|
-
var
|
|
645
|
-
var
|
|
620
|
+
// src/core/execute/ensurePermit2Allowance.ts
|
|
621
|
+
var import_viem5 = require("viem");
|
|
622
|
+
var import_intents_sdk9 = require("@shogun-sdk/intents-sdk");
|
|
646
623
|
async function ensurePermit2Allowance({
|
|
647
624
|
chainId,
|
|
648
625
|
tokenIn,
|
|
@@ -651,7 +628,7 @@ async function ensurePermit2Allowance({
|
|
|
651
628
|
requiredAmount,
|
|
652
629
|
increaseByDelta = false
|
|
653
630
|
}) {
|
|
654
|
-
const spender =
|
|
631
|
+
const spender = import_intents_sdk9.PERMIT2_ADDRESS[chainId];
|
|
655
632
|
let currentAllowance = 0n;
|
|
656
633
|
try {
|
|
657
634
|
if (!wallet.readContract) {
|
|
@@ -659,22 +636,22 @@ async function ensurePermit2Allowance({
|
|
|
659
636
|
}
|
|
660
637
|
currentAllowance = await wallet.readContract({
|
|
661
638
|
address: tokenIn,
|
|
662
|
-
abi:
|
|
639
|
+
abi: import_viem5.erc20Abi,
|
|
663
640
|
functionName: "allowance",
|
|
664
641
|
args: [accountAddress, spender]
|
|
665
642
|
});
|
|
666
643
|
} catch (error) {
|
|
667
644
|
console.warn(`[Permit2] Failed to read allowance for ${tokenIn}`, error);
|
|
668
645
|
}
|
|
669
|
-
const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount :
|
|
646
|
+
const approvalAmount = increaseByDelta ? currentAllowance + requiredAmount : import_viem5.maxUint256;
|
|
670
647
|
console.debug(
|
|
671
648
|
`[Permit2] Approving ${approvalAmount} for ${tokenIn} (current: ${currentAllowance}, required: ${requiredAmount})`
|
|
672
649
|
);
|
|
673
650
|
await wallet.sendTransaction({
|
|
674
651
|
to: tokenIn,
|
|
675
652
|
from: accountAddress,
|
|
676
|
-
data: (0,
|
|
677
|
-
abi:
|
|
653
|
+
data: (0, import_viem5.encodeFunctionData)({
|
|
654
|
+
abi: import_viem5.erc20Abi,
|
|
678
655
|
functionName: "approve",
|
|
679
656
|
args: [spender, approvalAmount]
|
|
680
657
|
}),
|
|
@@ -685,7 +662,7 @@ async function ensurePermit2Allowance({
|
|
|
685
662
|
);
|
|
686
663
|
}
|
|
687
664
|
|
|
688
|
-
// src/core/
|
|
665
|
+
// src/core/execute/handleEvmExecution.ts
|
|
689
666
|
async function handleEvmExecution({
|
|
690
667
|
recipientAddress,
|
|
691
668
|
quote,
|
|
@@ -693,19 +670,22 @@ async function handleEvmExecution({
|
|
|
693
670
|
accountAddress,
|
|
694
671
|
wallet,
|
|
695
672
|
isSingleChain,
|
|
696
|
-
|
|
697
|
-
|
|
673
|
+
update,
|
|
674
|
+
orderType,
|
|
675
|
+
options
|
|
698
676
|
}) {
|
|
699
|
-
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
|
|
677
|
+
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
|
|
678
|
+
const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
|
|
700
679
|
await wallet.switchChain(chainId);
|
|
701
680
|
const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
|
|
702
681
|
quote.tokenOut.address = normalizeEvmTokenAddress(quote.tokenOut.address);
|
|
703
682
|
const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
|
|
704
683
|
update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
|
|
705
684
|
if (shouldWrapNative) {
|
|
685
|
+
quote.tokenIn.address === tokenIn;
|
|
706
686
|
await wallet.sendTransaction({
|
|
707
687
|
to: tokenIn,
|
|
708
|
-
data: (0,
|
|
688
|
+
data: (0, import_viem6.encodeFunctionData)({
|
|
709
689
|
abi: [{ type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] }],
|
|
710
690
|
functionName: "deposit",
|
|
711
691
|
args: []
|
|
@@ -729,11 +709,13 @@ async function handleEvmExecution({
|
|
|
729
709
|
accountAddress,
|
|
730
710
|
destination,
|
|
731
711
|
deadline,
|
|
732
|
-
isSingleChain
|
|
712
|
+
isSingleChain,
|
|
713
|
+
orderType,
|
|
714
|
+
options
|
|
733
715
|
});
|
|
734
716
|
console.debug(`order`, order);
|
|
735
717
|
update("processing", messageFor("signing"));
|
|
736
|
-
const { orderTypedData, nonce } = isSingleChain ? await (0,
|
|
718
|
+
const { orderTypedData, nonce } = isSingleChain ? await (0, import_intents_sdk10.getEVMSingleChainOrderTypedData)(order) : await (0, import_intents_sdk10.getEVMCrossChainOrderTypedData)(order);
|
|
737
719
|
const typedData = serializeBigIntsToStrings(orderTypedData);
|
|
738
720
|
if (!wallet.signTypedData) {
|
|
739
721
|
throw new Error("Wallet does not support EIP-712 signing");
|
|
@@ -753,19 +735,30 @@ async function handleEvmExecution({
|
|
|
753
735
|
update("initiated", messageFor("initiated"));
|
|
754
736
|
const { intentId: orderId } = res.data;
|
|
755
737
|
update("initiated", messageFor("shogun_processing"));
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
738
|
+
if (orderType === "limit" /* LIMIT */) {
|
|
739
|
+
update("success", messageFor("success_limit"));
|
|
740
|
+
return {
|
|
741
|
+
status: true,
|
|
742
|
+
orderId,
|
|
743
|
+
chainId,
|
|
744
|
+
finalStatus: "OrderPlaced",
|
|
745
|
+
stage: "success"
|
|
746
|
+
};
|
|
747
|
+
} else {
|
|
748
|
+
const status = await pollOrderStatus(accountAddress, orderId);
|
|
749
|
+
return await handleOrderPollingResult({
|
|
750
|
+
status,
|
|
751
|
+
orderId,
|
|
752
|
+
chainId,
|
|
753
|
+
update,
|
|
754
|
+
messageFor
|
|
755
|
+
});
|
|
756
|
+
}
|
|
764
757
|
}
|
|
765
758
|
|
|
766
|
-
// src/core/
|
|
767
|
-
var
|
|
768
|
-
var
|
|
759
|
+
// src/core/execute/handleSolanaExecution.ts
|
|
760
|
+
var import_intents_sdk11 = require("@shogun-sdk/intents-sdk");
|
|
761
|
+
var import_web3 = require("@solana/web3.js");
|
|
769
762
|
async function handleSolanaExecution({
|
|
770
763
|
recipientAddress,
|
|
771
764
|
quote,
|
|
@@ -773,12 +766,14 @@ async function handleSolanaExecution({
|
|
|
773
766
|
isSingleChain,
|
|
774
767
|
update,
|
|
775
768
|
accountAddress,
|
|
776
|
-
|
|
769
|
+
orderType,
|
|
770
|
+
options
|
|
777
771
|
}) {
|
|
778
772
|
if (!wallet.rpcUrl) {
|
|
779
773
|
throw new Error("Solana wallet is missing rpcUrl");
|
|
780
774
|
}
|
|
781
|
-
const
|
|
775
|
+
const deadline = options?.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
|
|
776
|
+
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage] ?? "";
|
|
782
777
|
update("processing", messageFor("processing"));
|
|
783
778
|
const destination = recipientAddress ?? accountAddress;
|
|
784
779
|
const order = await buildOrder({
|
|
@@ -786,14 +781,16 @@ async function handleSolanaExecution({
|
|
|
786
781
|
accountAddress,
|
|
787
782
|
destination,
|
|
788
783
|
deadline,
|
|
789
|
-
isSingleChain
|
|
784
|
+
isSingleChain,
|
|
785
|
+
orderType,
|
|
786
|
+
options
|
|
790
787
|
});
|
|
791
788
|
const txData = await getSolanaOrderInstructions({
|
|
792
789
|
order,
|
|
793
790
|
isSingleChain,
|
|
794
791
|
rpcUrl: wallet.rpcUrl
|
|
795
792
|
});
|
|
796
|
-
const transaction =
|
|
793
|
+
const transaction = import_web3.VersionedTransaction.deserialize(Uint8Array.from(txData.txBytes));
|
|
797
794
|
update("processing", messageFor("signing"));
|
|
798
795
|
await wallet.sendTransaction(transaction);
|
|
799
796
|
update("processing", messageFor("submitting"));
|
|
@@ -806,16 +803,27 @@ async function handleSolanaExecution({
|
|
|
806
803
|
throw new Error("Auctioneer submission failed");
|
|
807
804
|
}
|
|
808
805
|
update("initiated", messageFor("initiated"));
|
|
809
|
-
const {
|
|
806
|
+
const { intentId: orderId } = response.data;
|
|
810
807
|
update("initiated", messageFor("shogun_processing"));
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
808
|
+
if (orderType === "limit" /* LIMIT */) {
|
|
809
|
+
update("success", messageFor("success_limit"));
|
|
810
|
+
return {
|
|
811
|
+
status: true,
|
|
812
|
+
orderId,
|
|
813
|
+
chainId: SOLANA_CHAIN_ID,
|
|
814
|
+
finalStatus: "OrderPlaced",
|
|
815
|
+
stage: "success"
|
|
816
|
+
};
|
|
817
|
+
} else {
|
|
818
|
+
const status = await pollOrderStatus(accountAddress, orderId);
|
|
819
|
+
return await handleOrderPollingResult({
|
|
820
|
+
status,
|
|
821
|
+
orderId,
|
|
822
|
+
chainId: SOLANA_CHAIN_ID,
|
|
823
|
+
update,
|
|
824
|
+
messageFor
|
|
825
|
+
});
|
|
826
|
+
}
|
|
819
827
|
}
|
|
820
828
|
async function getSolanaOrderInstructions({
|
|
821
829
|
order,
|
|
@@ -823,11 +831,11 @@ async function getSolanaOrderInstructions({
|
|
|
823
831
|
rpcUrl
|
|
824
832
|
}) {
|
|
825
833
|
if (isSingleChain) {
|
|
826
|
-
return await (0,
|
|
834
|
+
return await (0, import_intents_sdk11.getSolanaSingleChainOrderInstructions)(order, {
|
|
827
835
|
rpcUrl
|
|
828
836
|
});
|
|
829
837
|
}
|
|
830
|
-
return await (0,
|
|
838
|
+
return await (0, import_intents_sdk11.getSolanaCrossChainOrderInstructions)(order, {
|
|
831
839
|
rpcUrl
|
|
832
840
|
});
|
|
833
841
|
}
|
|
@@ -848,13 +856,14 @@ async function submitToAuctioneer({
|
|
|
848
856
|
});
|
|
849
857
|
}
|
|
850
858
|
|
|
851
|
-
// src/core/
|
|
859
|
+
// src/core/execute/execute.ts
|
|
852
860
|
async function executeOrder({
|
|
853
861
|
quote,
|
|
854
862
|
accountAddress,
|
|
855
863
|
recipientAddress,
|
|
856
864
|
wallet,
|
|
857
865
|
onStatus,
|
|
866
|
+
orderType = "market" /* MARKET */,
|
|
858
867
|
options = {}
|
|
859
868
|
}) {
|
|
860
869
|
const isDev = process.env.NODE_ENV !== "production";
|
|
@@ -867,21 +876,31 @@ async function executeOrder({
|
|
|
867
876
|
onStatus?.(stage, message ?? messageFor(stage));
|
|
868
877
|
};
|
|
869
878
|
try {
|
|
870
|
-
const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
|
|
871
879
|
log("Starting execution:", {
|
|
872
880
|
accountAddress,
|
|
873
881
|
recipientAddress,
|
|
874
|
-
deadline,
|
|
875
882
|
tokenIn: quote?.tokenIn,
|
|
876
883
|
tokenOut: quote?.tokenOut
|
|
877
884
|
});
|
|
878
885
|
const adapter = normalizeWallet(wallet);
|
|
879
886
|
if (!adapter) throw new Error("No wallet provided");
|
|
880
887
|
const { tokenIn, tokenOut } = quote;
|
|
888
|
+
const srcChain = Number(tokenIn.chainId);
|
|
889
|
+
const destChain = Number(tokenOut.chainId);
|
|
890
|
+
if (!CURRENT_SUPPORTED.includes(srcChain) || !CURRENT_SUPPORTED.includes(destChain)) {
|
|
891
|
+
const unsupportedChains = [
|
|
892
|
+
!CURRENT_SUPPORTED.includes(srcChain) ? srcChain : null,
|
|
893
|
+
!CURRENT_SUPPORTED.includes(destChain) ? destChain : null
|
|
894
|
+
].filter(Boolean).join(", ");
|
|
895
|
+
const errorMsg = `Unsupported chain(s): ${unsupportedChains}`;
|
|
896
|
+
update("error", errorMsg);
|
|
897
|
+
log("Error:", errorMsg);
|
|
898
|
+
throw new Error(errorMsg);
|
|
899
|
+
}
|
|
881
900
|
const isSingleChain = tokenIn.chainId === tokenOut.chainId;
|
|
882
901
|
const chainId = Number(tokenIn.chainId);
|
|
883
902
|
update("processing");
|
|
884
|
-
if ((0,
|
|
903
|
+
if ((0, import_intents_sdk12.isEvmChain)(chainId)) {
|
|
885
904
|
log("Detected EVM chain:", chainId);
|
|
886
905
|
const result = await handleEvmExecution({
|
|
887
906
|
recipientAddress,
|
|
@@ -890,13 +909,14 @@ async function executeOrder({
|
|
|
890
909
|
accountAddress,
|
|
891
910
|
wallet: adapter,
|
|
892
911
|
isSingleChain,
|
|
893
|
-
|
|
894
|
-
|
|
912
|
+
update,
|
|
913
|
+
orderType,
|
|
914
|
+
options
|
|
895
915
|
});
|
|
896
916
|
log("EVM execution result:", result);
|
|
897
917
|
return result;
|
|
898
918
|
}
|
|
899
|
-
if (chainId ===
|
|
919
|
+
if (chainId === import_intents_sdk12.ChainID.Solana) {
|
|
900
920
|
log("Detected Solana chain");
|
|
901
921
|
const result = await handleSolanaExecution({
|
|
902
922
|
recipientAddress,
|
|
@@ -904,8 +924,9 @@ async function executeOrder({
|
|
|
904
924
|
accountAddress,
|
|
905
925
|
wallet: adapter,
|
|
906
926
|
isSingleChain,
|
|
907
|
-
|
|
908
|
-
|
|
927
|
+
update,
|
|
928
|
+
orderType,
|
|
929
|
+
options
|
|
909
930
|
});
|
|
910
931
|
log("Solana execution result:", result);
|
|
911
932
|
return result;
|
|
@@ -915,8 +936,13 @@ async function executeOrder({
|
|
|
915
936
|
log("Error:", unsupported);
|
|
916
937
|
return { status: false, message: unsupported, stage: "error" };
|
|
917
938
|
} catch (error) {
|
|
918
|
-
|
|
919
|
-
|
|
939
|
+
let message = "An unknown error occurred";
|
|
940
|
+
if (error && typeof error === "object") {
|
|
941
|
+
const err = error;
|
|
942
|
+
message = err.details ?? err.message ?? message;
|
|
943
|
+
} else if (typeof error === "string") {
|
|
944
|
+
message = error;
|
|
945
|
+
}
|
|
920
946
|
update("error", message);
|
|
921
947
|
return { status: false, message, stage: "error" };
|
|
922
948
|
}
|
|
@@ -927,299 +953,177 @@ function normalizeWallet(wallet) {
|
|
|
927
953
|
return wallet;
|
|
928
954
|
}
|
|
929
955
|
|
|
930
|
-
// src/
|
|
931
|
-
var
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
const debounceRef = (0, import_react.useRef)(null);
|
|
939
|
-
const debounceMs = params.debounceMs ?? 250;
|
|
940
|
-
const cacheKey = (0, import_react.useMemo)(() => {
|
|
941
|
-
return JSON.stringify({
|
|
942
|
-
q: params.q?.trim().toLowerCase() ?? "",
|
|
943
|
-
networkId: params.networkId ?? "all",
|
|
944
|
-
page: params.page ?? 1,
|
|
945
|
-
limit: params.limit ?? 50
|
|
946
|
-
});
|
|
947
|
-
}, [params.q, params.networkId, params.page, params.limit]);
|
|
948
|
-
async function fetchTokens(signal) {
|
|
949
|
-
if (tokenCache.has(cacheKey)) {
|
|
950
|
-
setData(tokenCache.get(cacheKey));
|
|
951
|
-
setLoading(false);
|
|
952
|
-
setError(null);
|
|
953
|
-
return;
|
|
954
|
-
}
|
|
955
|
-
try {
|
|
956
|
-
setLoading(true);
|
|
957
|
-
const result = await getTokenList({ ...params, signal });
|
|
958
|
-
tokenCache.set(cacheKey, result);
|
|
959
|
-
setData(result);
|
|
960
|
-
setError(null);
|
|
961
|
-
} catch (err) {
|
|
962
|
-
if (err.name !== "AbortError") {
|
|
963
|
-
const e = err instanceof Error ? err : new Error("Unknown error while fetching tokens");
|
|
964
|
-
setError(e);
|
|
965
|
-
}
|
|
966
|
-
} finally {
|
|
967
|
-
setLoading(false);
|
|
968
|
-
}
|
|
956
|
+
// src/core/orders/getOrders.ts
|
|
957
|
+
var import_intents_sdk13 = require("@shogun-sdk/intents-sdk");
|
|
958
|
+
async function getOrders({
|
|
959
|
+
evmAddress,
|
|
960
|
+
solAddress
|
|
961
|
+
}) {
|
|
962
|
+
if (!evmAddress && !solAddress) {
|
|
963
|
+
throw new Error("At least one wallet address (EVM, Solana) must be provided.");
|
|
969
964
|
}
|
|
970
|
-
(0,
|
|
971
|
-
|
|
972
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
973
|
-
if (controllerRef.current) controllerRef.current.abort();
|
|
974
|
-
const controller = new AbortController();
|
|
975
|
-
controllerRef.current = controller;
|
|
976
|
-
debounceRef.current = setTimeout(() => {
|
|
977
|
-
fetchTokens(controller.signal);
|
|
978
|
-
}, debounceMs);
|
|
979
|
-
return () => {
|
|
980
|
-
controller.abort();
|
|
981
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
982
|
-
};
|
|
983
|
-
}, [cacheKey, debounceMs]);
|
|
984
|
-
return (0, import_react.useMemo)(
|
|
985
|
-
() => ({
|
|
986
|
-
/** Current fetched data (cached when possible) */
|
|
987
|
-
data,
|
|
988
|
-
/** Whether a request is in progress */
|
|
989
|
-
loading,
|
|
990
|
-
/** Error object if a request failed */
|
|
991
|
-
error,
|
|
992
|
-
/** Manually refetch the token list */
|
|
993
|
-
refetch: () => fetchTokens(),
|
|
994
|
-
/** Clear all cached token results (shared across hook instances) */
|
|
995
|
-
clearCache: () => tokenCache.clear()
|
|
996
|
-
}),
|
|
997
|
-
[data, loading, error]
|
|
998
|
-
);
|
|
965
|
+
const orders = await (0, import_intents_sdk13.fetchUserOrders)(evmAddress, solAddress);
|
|
966
|
+
return orders;
|
|
999
967
|
}
|
|
1000
968
|
|
|
1001
|
-
// src/
|
|
1002
|
-
var
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
969
|
+
// src/core/client.ts
|
|
970
|
+
var SwapSDK = class {
|
|
971
|
+
constructor(config) {
|
|
972
|
+
__publicField(this, "apiKey");
|
|
973
|
+
/**
|
|
974
|
+
* Fetches metadata for one or more tokens from the Shogun Token Search API.
|
|
975
|
+
*
|
|
976
|
+
* ---
|
|
977
|
+
* ### Overview
|
|
978
|
+
* `getTokensData` retrieves normalized token information — such as symbol, name,
|
|
979
|
+
* decimals, logo URI, and verified status — for a given list of token addresses.
|
|
980
|
+
*
|
|
981
|
+
* It supports both **EVM** and **SVM (Solana)** tokens, returning metadata from
|
|
982
|
+
* Shogun’s unified token registry.
|
|
983
|
+
*
|
|
984
|
+
* ---
|
|
985
|
+
* @example
|
|
986
|
+
* ```ts
|
|
987
|
+
* const tokens = await getTokensData([
|
|
988
|
+
* "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
|
|
989
|
+
* "So11111111111111111111111111111111111111112", // SOL
|
|
990
|
+
* ]);
|
|
991
|
+
*
|
|
992
|
+
* console.log(tokens);
|
|
993
|
+
* [
|
|
994
|
+
* { symbol: "USDC", name: "USD Coin", chainId: 1, decimals: 6, ... },
|
|
995
|
+
* { symbol: "SOL", name: "Solana", chainId: 101, decimals: 9, ... }
|
|
996
|
+
* ]
|
|
997
|
+
* ```
|
|
998
|
+
*
|
|
999
|
+
* @param addresses - An array of token addresses (EVM or SVM) to fetch metadata for.
|
|
1000
|
+
* @returns A promise resolving to an array of {@link TokenInfo} objects.
|
|
1001
|
+
*
|
|
1002
|
+
* @throws Will throw an error if the network request fails or the API responds with a non-OK status.
|
|
1003
|
+
*/
|
|
1004
|
+
__publicField(this, "getTokensData", getTokensData.bind(this));
|
|
1005
|
+
if (!config.apiKey) {
|
|
1006
|
+
throw new Error("SwapSDK: Missing API key");
|
|
1007
|
+
}
|
|
1008
|
+
this.apiKey = config.apiKey;
|
|
1009
|
+
if (this.apiKey) void this.apiKey;
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Retrieves a swap quote for the given input and output tokens.
|
|
1013
|
+
*
|
|
1014
|
+
* @param params - Quote parameters including source/destination tokens and amount.
|
|
1015
|
+
* @returns A normalized `SwapQuoteResponse` containing output amount, route, and metadata.
|
|
1016
|
+
*/
|
|
1017
|
+
async getQuote(params) {
|
|
1018
|
+
return getQuote(params);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Fetches token balances for the specified user wallet(s).
|
|
1022
|
+
*
|
|
1023
|
+
* Supports both EVM and SVM (Solana) wallet addresses.
|
|
1024
|
+
*
|
|
1025
|
+
* @param params - Wallet address and optional chain filters.
|
|
1026
|
+
* @param options - Optional abort signal for cancellation.
|
|
1027
|
+
* @returns A unified balance response with per-chain token details.
|
|
1028
|
+
*/
|
|
1029
|
+
async getBalances(params, options) {
|
|
1030
|
+
return getBalances(params, options);
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Retrieves a list of verified tokens based on search query or chain filter.
|
|
1034
|
+
*
|
|
1035
|
+
* @param params - Search parameters (query, chain ID, pagination options).
|
|
1036
|
+
* @returns Paginated `TokenSearchResponse` containing token metadata.
|
|
1037
|
+
*/
|
|
1038
|
+
async getTokenList(params) {
|
|
1039
|
+
return getTokenList(params);
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Executes a prepared swap quote using the provided wallet and configuration.
|
|
1043
|
+
*
|
|
1044
|
+
* Handles:
|
|
1045
|
+
* - Token approval (if required)
|
|
1046
|
+
* - Transaction signing and broadcasting
|
|
1047
|
+
* - Confirmation polling and stage-based status updates
|
|
1048
|
+
*
|
|
1049
|
+
* Supports both:
|
|
1050
|
+
* - Market orders (with optional deadline)
|
|
1051
|
+
* - Limit orders (requires executionPrice and deadline)
|
|
1052
|
+
*
|
|
1053
|
+
* @param quote - The swap quote to execute, containing route and metadata.
|
|
1054
|
+
* @param accountAddress - The user's wallet address executing the swap.
|
|
1055
|
+
* @param recipientAddress - Optional recipient address for the output tokens (defaults to sender).
|
|
1056
|
+
* @param wallet - Adapted wallet instance (EVM/Solana) or a standard Viem `WalletClient`.
|
|
1057
|
+
* @param onStatus - Optional callback for receiving execution stage updates and messages.
|
|
1058
|
+
* @param orderType - Defines whether this is a market or limit order.
|
|
1059
|
+
* @param options - Execution parameters (different per order type).
|
|
1060
|
+
*
|
|
1061
|
+
* @returns A finalized execution result containing transaction hash, status, and any returned data.
|
|
1062
|
+
*
|
|
1063
|
+
* @example
|
|
1064
|
+
* ```ts
|
|
1065
|
+
* * Market order
|
|
1066
|
+
* const result = await sdk.executeTransaction({
|
|
1067
|
+
* quote,
|
|
1068
|
+
* accountAddress: "0x123...",
|
|
1069
|
+
* wallet,
|
|
1070
|
+
* orderType: OrderExecutionType.MARKET,
|
|
1071
|
+
* options: { deadline: 1800 },
|
|
1072
|
+
* onStatus: (stage, msg) => console.log(stage, msg),
|
|
1073
|
+
* });
|
|
1074
|
+
*
|
|
1075
|
+
* * Limit order
|
|
1076
|
+
* const result = await sdk.executeTransaction({
|
|
1077
|
+
* quote,
|
|
1078
|
+
* accountAddress: "0x123...",
|
|
1079
|
+
* wallet,
|
|
1080
|
+
* orderType: OrderExecutionType.LIMIT,
|
|
1081
|
+
* options: { executionPrice: "0.0021", deadline: 3600 },
|
|
1082
|
+
* });
|
|
1083
|
+
* ```
|
|
1084
|
+
*/
|
|
1085
|
+
async executeTransaction({
|
|
1086
|
+
quote,
|
|
1087
|
+
accountAddress,
|
|
1088
|
+
recipientAddress,
|
|
1089
|
+
wallet,
|
|
1090
|
+
onStatus,
|
|
1091
|
+
orderType,
|
|
1092
|
+
options
|
|
1093
|
+
}) {
|
|
1094
|
+
return executeOrder({
|
|
1017
1095
|
quote,
|
|
1096
|
+
wallet,
|
|
1018
1097
|
accountAddress,
|
|
1019
1098
|
recipientAddress,
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
if (!quote || !wallet) {
|
|
1024
|
-
throw new Error("Quote and wallet are required for order execution.");
|
|
1025
|
-
}
|
|
1026
|
-
setLoading(true);
|
|
1027
|
-
setError(null);
|
|
1028
|
-
setData(null);
|
|
1029
|
-
setMessage(null);
|
|
1030
|
-
try {
|
|
1031
|
-
const effectiveDeadline = deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
|
|
1032
|
-
const onStatus = (stage, msg) => {
|
|
1033
|
-
if (!isMounted.current) return;
|
|
1034
|
-
setStatus(stage);
|
|
1035
|
-
if (msg) setMessage(msg);
|
|
1036
|
-
};
|
|
1037
|
-
const result = await executeOrder({
|
|
1038
|
-
quote,
|
|
1039
|
-
accountAddress,
|
|
1040
|
-
recipientAddress,
|
|
1041
|
-
wallet,
|
|
1042
|
-
onStatus,
|
|
1043
|
-
options: { deadline: effectiveDeadline }
|
|
1044
|
-
});
|
|
1045
|
-
if (!isMounted.current) return result;
|
|
1046
|
-
setData(result);
|
|
1047
|
-
setStatus(result.stage);
|
|
1048
|
-
setMessage("Order executed successfully");
|
|
1049
|
-
return result;
|
|
1050
|
-
} catch (err) {
|
|
1051
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1052
|
-
if (isMounted.current) {
|
|
1053
|
-
setError(errorObj);
|
|
1054
|
-
setStatus("error");
|
|
1055
|
-
setMessage(errorObj.message);
|
|
1056
|
-
setData({
|
|
1057
|
-
status: false,
|
|
1058
|
-
stage: "error",
|
|
1059
|
-
message: errorObj.message
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
return {
|
|
1063
|
-
status: false,
|
|
1064
|
-
stage: "error",
|
|
1065
|
-
message: errorObj.message
|
|
1066
|
-
};
|
|
1067
|
-
} finally {
|
|
1068
|
-
if (isMounted.current) setLoading(false);
|
|
1069
|
-
}
|
|
1070
|
-
},
|
|
1071
|
-
[]
|
|
1072
|
-
);
|
|
1073
|
-
return {
|
|
1074
|
-
/** Executes the swap order. */
|
|
1075
|
-
execute,
|
|
1076
|
-
/** Current execution stage. */
|
|
1077
|
-
status,
|
|
1078
|
-
/** Human-readable status message. */
|
|
1079
|
-
message,
|
|
1080
|
-
/** Whether execution is ongoing. */
|
|
1081
|
-
loading,
|
|
1082
|
-
/** Raw SDK response data. */
|
|
1083
|
-
data,
|
|
1084
|
-
/** Captured error (if execution failed). */
|
|
1085
|
-
error
|
|
1086
|
-
};
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// src/react/useQuote.ts
|
|
1090
|
-
var import_react3 = require("react");
|
|
1091
|
-
function useQuote(params, options) {
|
|
1092
|
-
const [data, setData] = (0, import_react3.useState)(null);
|
|
1093
|
-
const [loading, setLoading] = (0, import_react3.useState)(false);
|
|
1094
|
-
const [error, setError] = (0, import_react3.useState)(null);
|
|
1095
|
-
const [warning, setWarning] = (0, import_react3.useState)(null);
|
|
1096
|
-
const debounceMs = options?.debounceMs ?? 250;
|
|
1097
|
-
const autoRefreshMs = options?.autoRefreshMs;
|
|
1098
|
-
const abortRef = (0, import_react3.useRef)(null);
|
|
1099
|
-
const debounceRef = (0, import_react3.useRef)(null);
|
|
1100
|
-
const mounted = (0, import_react3.useRef)(false);
|
|
1101
|
-
const paramsKey = (0, import_react3.useMemo)(
|
|
1102
|
-
() => params ? JSON.stringify(serializeBigIntsToStrings(params)) : null,
|
|
1103
|
-
[params]
|
|
1104
|
-
);
|
|
1105
|
-
(0, import_react3.useEffect)(() => {
|
|
1106
|
-
mounted.current = true;
|
|
1107
|
-
return () => {
|
|
1108
|
-
mounted.current = false;
|
|
1109
|
-
abortRef.current?.abort();
|
|
1110
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
1111
|
-
};
|
|
1112
|
-
}, []);
|
|
1113
|
-
const fetchQuote = (0, import_react3.useCallback)(async () => {
|
|
1114
|
-
if (!params) return;
|
|
1115
|
-
try {
|
|
1116
|
-
setLoading(true);
|
|
1117
|
-
setWarning(null);
|
|
1118
|
-
const result = await getQuote(params);
|
|
1119
|
-
const serializeResult = serializeBigIntsToStrings(result);
|
|
1120
|
-
if (!mounted.current) return;
|
|
1121
|
-
setData((prev) => {
|
|
1122
|
-
if (JSON.stringify(prev) === JSON.stringify(serializeResult)) return prev;
|
|
1123
|
-
return serializeResult;
|
|
1124
|
-
});
|
|
1125
|
-
setWarning(result.warning ?? null);
|
|
1126
|
-
setError(null);
|
|
1127
|
-
} catch (err) {
|
|
1128
|
-
if (err.name === "AbortError") return;
|
|
1129
|
-
console.error("[useQuote] fetch error:", err);
|
|
1130
|
-
if (mounted.current) setError(err instanceof Error ? err : new Error(String(err)));
|
|
1131
|
-
} finally {
|
|
1132
|
-
if (mounted.current) setLoading(false);
|
|
1133
|
-
}
|
|
1134
|
-
}, [paramsKey]);
|
|
1135
|
-
(0, import_react3.useEffect)(() => {
|
|
1136
|
-
if (!paramsKey) return;
|
|
1137
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
1138
|
-
debounceRef.current = setTimeout(() => {
|
|
1139
|
-
fetchQuote();
|
|
1140
|
-
}, debounceMs);
|
|
1141
|
-
return () => {
|
|
1142
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
1143
|
-
abortRef.current?.abort();
|
|
1144
|
-
};
|
|
1145
|
-
}, [paramsKey, debounceMs, fetchQuote]);
|
|
1146
|
-
(0, import_react3.useEffect)(() => {
|
|
1147
|
-
if (!autoRefreshMs || !paramsKey) return;
|
|
1148
|
-
const interval = setInterval(() => fetchQuote(), autoRefreshMs);
|
|
1149
|
-
return () => clearInterval(interval);
|
|
1150
|
-
}, [autoRefreshMs, paramsKey, fetchQuote]);
|
|
1151
|
-
return (0, import_react3.useMemo)(
|
|
1152
|
-
() => ({
|
|
1153
|
-
data,
|
|
1154
|
-
loading,
|
|
1155
|
-
error,
|
|
1156
|
-
warning,
|
|
1157
|
-
refetch: fetchQuote
|
|
1158
|
-
}),
|
|
1159
|
-
[data, loading, error, warning, fetchQuote]
|
|
1160
|
-
);
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
// src/react/useBalances.ts
|
|
1164
|
-
var import_react4 = require("react");
|
|
1165
|
-
function useBalances(params) {
|
|
1166
|
-
const [data, setData] = (0, import_react4.useState)(null);
|
|
1167
|
-
const [loading, setLoading] = (0, import_react4.useState)(false);
|
|
1168
|
-
const [error, setError] = (0, import_react4.useState)(null);
|
|
1169
|
-
const abortRef = (0, import_react4.useRef)(null);
|
|
1170
|
-
const stableParams = (0, import_react4.useMemo)(() => {
|
|
1171
|
-
if (!params) return null;
|
|
1172
|
-
const { addresses, cursorEvm, cursorSvm } = params;
|
|
1173
|
-
return {
|
|
1174
|
-
addresses: {
|
|
1175
|
-
evm: addresses?.evm ?? void 0,
|
|
1176
|
-
svm: addresses?.svm ?? void 0
|
|
1177
|
-
},
|
|
1178
|
-
cursorEvm,
|
|
1179
|
-
cursorSvm
|
|
1180
|
-
};
|
|
1181
|
-
}, [params?.addresses?.evm, params?.addresses?.svm, params?.cursorEvm, params?.cursorSvm]);
|
|
1182
|
-
const fetchBalances = (0, import_react4.useCallback)(async () => {
|
|
1183
|
-
if (!stableParams) return;
|
|
1184
|
-
if (abortRef.current) abortRef.current.abort();
|
|
1185
|
-
const controller = new AbortController();
|
|
1186
|
-
abortRef.current = controller;
|
|
1187
|
-
setLoading(true);
|
|
1188
|
-
setError(null);
|
|
1189
|
-
try {
|
|
1190
|
-
const result = await getBalances(stableParams, { signal: controller.signal });
|
|
1191
|
-
setData((prev) => {
|
|
1192
|
-
if (JSON.stringify(prev) === JSON.stringify(result)) return prev;
|
|
1193
|
-
return result;
|
|
1194
|
-
});
|
|
1195
|
-
return result;
|
|
1196
|
-
} catch (err) {
|
|
1197
|
-
if (err.name === "AbortError") return;
|
|
1198
|
-
const e = err instanceof Error ? err : new Error(String(err));
|
|
1199
|
-
setError(e);
|
|
1200
|
-
throw e;
|
|
1201
|
-
} finally {
|
|
1202
|
-
setLoading(false);
|
|
1203
|
-
}
|
|
1204
|
-
}, [stableParams]);
|
|
1205
|
-
(0, import_react4.useEffect)(() => {
|
|
1206
|
-
if (stableParams) fetchBalances().catch(() => {
|
|
1099
|
+
onStatus,
|
|
1100
|
+
orderType,
|
|
1101
|
+
options
|
|
1207
1102
|
});
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Fetches all user orders (Market, Limit, Cross-chain) for connected wallets.
|
|
1106
|
+
*
|
|
1107
|
+
* ---
|
|
1108
|
+
* ### Overview
|
|
1109
|
+
* Retrieves both **single-chain** and **cross-chain** orders from the Shogun Intents API.
|
|
1110
|
+
* Works across EVM, Solana
|
|
1111
|
+
*
|
|
1112
|
+
* ---
|
|
1113
|
+
* @example
|
|
1114
|
+
* ```ts
|
|
1115
|
+
* const orders = await sdk.getOrders({
|
|
1116
|
+
* evmAddress: "0x123...",
|
|
1117
|
+
* solAddress: "9d12hF...abc",
|
|
1118
|
+
* });
|
|
1119
|
+
*
|
|
1120
|
+
* console.log(orders.singleChainLimitOrders);
|
|
1121
|
+
* ```
|
|
1122
|
+
*
|
|
1123
|
+
* @param params - Wallet addresses to fetch orders for (EVM, Solana).
|
|
1124
|
+
* @returns A structured {@link ApiUserOrders} object containing all user orders.
|
|
1125
|
+
*/
|
|
1126
|
+
async getOrders(params) {
|
|
1127
|
+
return getOrders(params);
|
|
1128
|
+
}
|
|
1129
|
+
};
|