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