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