@shogun-sdk/swap 0.0.2-test
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/README.md +274 -0
- package/dist/core.cjs +619 -0
- package/dist/core.d.cts +137 -0
- package/dist/core.d.ts +137 -0
- package/dist/core.js +590 -0
- package/dist/execute-FaLLPp1i.d.cts +147 -0
- package/dist/execute-HX1fQ7wG.d.ts +147 -0
- package/dist/index.cjs +2477 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +2458 -0
- package/dist/react.cjs +2364 -0
- package/dist/react.d.cts +158 -0
- package/dist/react.d.ts +158 -0
- package/dist/react.js +2355 -0
- package/dist/wallet-MmUIz8GE.d.cts +29 -0
- package/dist/wallet-MmUIz8GE.d.ts +29 -0
- package/dist/wallet-adapter.cjs +175 -0
- package/dist/wallet-adapter.d.cts +34 -0
- package/dist/wallet-adapter.d.ts +34 -0
- package/dist/wallet-adapter.js +150 -0
- package/package.json +68 -0
package/dist/core.js
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
// src/core/token-list.ts
|
|
2
|
+
import { getTokenList as intentsGetTokenList } from "@shogun-sdk/intents-sdk";
|
|
3
|
+
async function getTokenList(params) {
|
|
4
|
+
return intentsGetTokenList(params);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// src/core/getQuote.ts
|
|
8
|
+
import { QuoteProvider } from "@shogun-sdk/intents-sdk";
|
|
9
|
+
import { parseUnits } from "viem";
|
|
10
|
+
|
|
11
|
+
// src/core/executeOrder/normalizeNative.ts
|
|
12
|
+
import { isEvmChain } from "@shogun-sdk/intents-sdk";
|
|
13
|
+
|
|
14
|
+
// src/utils/address.ts
|
|
15
|
+
var NATIVE_TOKEN = {
|
|
16
|
+
ETH: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
17
|
+
SOL: "So11111111111111111111111111111111111111111",
|
|
18
|
+
SUI: "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
|
|
19
|
+
};
|
|
20
|
+
var isNativeAddress = (tokenAddress) => {
|
|
21
|
+
const NATIVE_ADDRESSES = Object.values(SupportedChains).map((chain) => chain.tokenAddress.toLowerCase());
|
|
22
|
+
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
|
23
|
+
return !!tokenAddress && NATIVE_ADDRESSES.includes(normalizedTokenAddress);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/utils/chain.ts
|
|
27
|
+
import { ChainID } from "@shogun-sdk/intents-sdk";
|
|
28
|
+
var SOLANA_CHAIN_ID = ChainID.Solana;
|
|
29
|
+
var SupportedChains = [
|
|
30
|
+
{
|
|
31
|
+
id: ChainID.Arbitrum,
|
|
32
|
+
name: "Arbitrum",
|
|
33
|
+
isEVM: true,
|
|
34
|
+
wrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
35
|
+
symbol: "ETH",
|
|
36
|
+
decimals: 18,
|
|
37
|
+
tokenAddress: NATIVE_TOKEN.ETH
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: ChainID.Optimism,
|
|
41
|
+
name: "Optimism",
|
|
42
|
+
isEVM: true,
|
|
43
|
+
wrapped: "0x4200000000000000000000000000000000000006",
|
|
44
|
+
symbol: "ETH",
|
|
45
|
+
decimals: 18,
|
|
46
|
+
tokenAddress: NATIVE_TOKEN.ETH
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: ChainID.Base,
|
|
50
|
+
name: "Base",
|
|
51
|
+
isEVM: true,
|
|
52
|
+
wrapped: "0x4200000000000000000000000000000000000006",
|
|
53
|
+
symbol: "ETH",
|
|
54
|
+
decimals: 18,
|
|
55
|
+
tokenAddress: NATIVE_TOKEN.ETH
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: ChainID.Hyperliquid,
|
|
59
|
+
name: "Hyperliquid",
|
|
60
|
+
isEVM: true,
|
|
61
|
+
wrapped: "0x5555555555555555555555555555555555555555",
|
|
62
|
+
symbol: "ETH",
|
|
63
|
+
decimals: 18,
|
|
64
|
+
tokenAddress: NATIVE_TOKEN.ETH
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: ChainID.BSC,
|
|
68
|
+
name: "BSC",
|
|
69
|
+
isEVM: true,
|
|
70
|
+
wrapped: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
71
|
+
symbol: "BNB",
|
|
72
|
+
decimals: 18,
|
|
73
|
+
tokenAddress: NATIVE_TOKEN.ETH
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: SOLANA_CHAIN_ID,
|
|
77
|
+
name: "Solana",
|
|
78
|
+
isEVM: false,
|
|
79
|
+
wrapped: "So11111111111111111111111111111111111111112",
|
|
80
|
+
symbol: "SOL",
|
|
81
|
+
decimals: 9,
|
|
82
|
+
tokenAddress: NATIVE_TOKEN.SOL
|
|
83
|
+
}
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
// src/utils/viem.ts
|
|
87
|
+
function isViemWalletClient(wallet) {
|
|
88
|
+
return wallet.extend !== void 0 && wallet.getPermissions !== void 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/utils/number.ts
|
|
92
|
+
function serializeBigIntsToStrings(obj) {
|
|
93
|
+
if (typeof obj === "bigint") {
|
|
94
|
+
return obj.toString();
|
|
95
|
+
}
|
|
96
|
+
if (typeof obj === "string" && /^\d+n$/.test(obj)) {
|
|
97
|
+
return obj.slice(0, -1);
|
|
98
|
+
}
|
|
99
|
+
if (Array.isArray(obj)) {
|
|
100
|
+
return obj.map((item) => serializeBigIntsToStrings(item));
|
|
101
|
+
}
|
|
102
|
+
if (obj && typeof obj === "object") {
|
|
103
|
+
const result = {};
|
|
104
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
105
|
+
result[key] = serializeBigIntsToStrings(value);
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
return obj;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/core/executeOrder/normalizeNative.ts
|
|
113
|
+
function normalizeNative(chainId, address) {
|
|
114
|
+
if (isEvmChain(chainId) && isNativeAddress(address)) {
|
|
115
|
+
const chain = SupportedChains.find((c) => c.id === chainId);
|
|
116
|
+
if (!chain?.wrapped)
|
|
117
|
+
throw new Error(`Wrapped token not found for chainId ${chainId}`);
|
|
118
|
+
return chain.wrapped;
|
|
119
|
+
}
|
|
120
|
+
return address;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/core/getQuote.ts
|
|
124
|
+
async function getQuote(params) {
|
|
125
|
+
if (!params.tokenIn?.address || !params.tokenOut?.address) {
|
|
126
|
+
throw new Error("Both tokenIn and tokenOut must include an address.");
|
|
127
|
+
}
|
|
128
|
+
if (!params.sourceChainId || !params.destChainId) {
|
|
129
|
+
throw new Error("Both sourceChainId and destChainId are required.");
|
|
130
|
+
}
|
|
131
|
+
if (params.amount <= 0n) {
|
|
132
|
+
throw new Error("Amount must be greater than 0.");
|
|
133
|
+
}
|
|
134
|
+
const normalizedTokenIn = normalizeNative(params.sourceChainId, params.tokenIn.address);
|
|
135
|
+
const data = await QuoteProvider.getQuote({
|
|
136
|
+
sourceChainId: params.sourceChainId,
|
|
137
|
+
destChainId: params.destChainId,
|
|
138
|
+
tokenIn: normalizedTokenIn,
|
|
139
|
+
tokenOut: params.tokenOut.address,
|
|
140
|
+
amount: params.amount
|
|
141
|
+
});
|
|
142
|
+
const inputSlippage = params.slippage ?? 5;
|
|
143
|
+
const slippageDecimal = inputSlippage / 100;
|
|
144
|
+
const slippage = Math.min(Math.max(slippageDecimal, 0), 0.5);
|
|
145
|
+
let warning;
|
|
146
|
+
if (slippage > 0.1) {
|
|
147
|
+
warning = `\u26A0\uFE0F High slippage tolerance (${(slippage * 100).toFixed(2)}%) \u2014 price may vary significantly.`;
|
|
148
|
+
}
|
|
149
|
+
const estimatedAmountOut = BigInt(data.estimatedAmountOutReduced);
|
|
150
|
+
const slippageBps = BigInt(Math.round(slippage * 1e4));
|
|
151
|
+
const estimatedAmountOutAfterSlippage = estimatedAmountOut * (10000n - slippageBps) / 10000n;
|
|
152
|
+
const pricePerInputToken = estimatedAmountOut * 10n ** BigInt(params.tokenIn.decimals ?? 18) / BigInt(params.amount);
|
|
153
|
+
return {
|
|
154
|
+
amountOut: estimatedAmountOut,
|
|
155
|
+
amountOutUsd: data.estimatedAmountOutUsd,
|
|
156
|
+
amountInUsd: data.amountInUsd,
|
|
157
|
+
minStablecoinsAmount: data.estimatedAmountInAsMinStablecoinAmount,
|
|
158
|
+
tokenIn: {
|
|
159
|
+
address: params.tokenIn.address,
|
|
160
|
+
decimals: params.tokenIn.decimals ?? 18,
|
|
161
|
+
chainId: params.sourceChainId
|
|
162
|
+
},
|
|
163
|
+
tokenOut: {
|
|
164
|
+
address: params.tokenOut.address,
|
|
165
|
+
decimals: params.tokenOut.decimals ?? 18,
|
|
166
|
+
chainId: params.destChainId
|
|
167
|
+
},
|
|
168
|
+
amountIn: params.amount,
|
|
169
|
+
pricePerInputToken,
|
|
170
|
+
slippage,
|
|
171
|
+
internal: {
|
|
172
|
+
...data,
|
|
173
|
+
estimatedAmountOutReduced: estimatedAmountOutAfterSlippage
|
|
174
|
+
},
|
|
175
|
+
warning
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function buildQuoteParams({
|
|
179
|
+
tokenIn,
|
|
180
|
+
tokenOut,
|
|
181
|
+
sourceChainId,
|
|
182
|
+
destChainId,
|
|
183
|
+
amount,
|
|
184
|
+
slippage
|
|
185
|
+
}) {
|
|
186
|
+
return {
|
|
187
|
+
tokenIn,
|
|
188
|
+
tokenOut,
|
|
189
|
+
sourceChainId,
|
|
190
|
+
destChainId,
|
|
191
|
+
amount: parseUnits(amount.toString(), tokenIn.decimals ?? 18),
|
|
192
|
+
slippage
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/core/getBalances.ts
|
|
197
|
+
import { TOKEN_SEARCH_API_BASE_URL } from "@shogun-sdk/intents-sdk";
|
|
198
|
+
async function getBalances(params, options) {
|
|
199
|
+
const { addresses, cursorEvm, cursorSvm } = params;
|
|
200
|
+
const { signal } = options ?? {};
|
|
201
|
+
if (!addresses?.evm && !addresses?.svm) {
|
|
202
|
+
throw new Error("At least one address (EVM or SVM) must be provided.");
|
|
203
|
+
}
|
|
204
|
+
const payload = JSON.stringify({
|
|
205
|
+
addresses,
|
|
206
|
+
cursorEvm,
|
|
207
|
+
cursorSvm
|
|
208
|
+
});
|
|
209
|
+
const start = performance.now();
|
|
210
|
+
const response = await fetch(`${TOKEN_SEARCH_API_BASE_URL}/tokens/balances`, {
|
|
211
|
+
method: "POST",
|
|
212
|
+
headers: {
|
|
213
|
+
accept: "application/json",
|
|
214
|
+
"Content-Type": "application/json"
|
|
215
|
+
},
|
|
216
|
+
body: payload,
|
|
217
|
+
signal
|
|
218
|
+
}).catch((err) => {
|
|
219
|
+
if (err.name === "AbortError") {
|
|
220
|
+
throw new Error("Balance request was cancelled.");
|
|
221
|
+
}
|
|
222
|
+
throw err;
|
|
223
|
+
});
|
|
224
|
+
if (!response.ok) {
|
|
225
|
+
const text = await response.text().catch(() => "");
|
|
226
|
+
throw new Error(`Failed to fetch balances: ${response.status} ${text}`);
|
|
227
|
+
}
|
|
228
|
+
const data = await response.json().catch(() => {
|
|
229
|
+
throw new Error("Invalid JSON response from balances API.");
|
|
230
|
+
});
|
|
231
|
+
const duration = (performance.now() - start).toFixed(1);
|
|
232
|
+
if (process.env.NODE_ENV !== "production") {
|
|
233
|
+
console.debug(`[Shogun SDK] Fetched balances in ${duration}ms`);
|
|
234
|
+
}
|
|
235
|
+
const evmItems = data.evm?.items ?? [];
|
|
236
|
+
const svmItems = data.svm?.items ?? [];
|
|
237
|
+
const combined = [...evmItems, ...svmItems];
|
|
238
|
+
return {
|
|
239
|
+
results: combined,
|
|
240
|
+
nextCursorEvm: data.evm?.cursor ?? null,
|
|
241
|
+
nextCursorSvm: data.svm?.cursor ?? null
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/core/executeOrder/execute.ts
|
|
246
|
+
import { ChainID as ChainID4, isEvmChain as isEvmChain2 } from "@shogun-sdk/intents-sdk";
|
|
247
|
+
import { BaseError } from "viem";
|
|
248
|
+
|
|
249
|
+
// src/wallet-adapter/evm-wallet-adapter/adapter.ts
|
|
250
|
+
import "ethers/lib/ethers.js";
|
|
251
|
+
import { hexValue } from "ethers/lib/utils.js";
|
|
252
|
+
import {
|
|
253
|
+
custom
|
|
254
|
+
} from "viem";
|
|
255
|
+
function isEVMTransaction(tx) {
|
|
256
|
+
return typeof tx.from === "string";
|
|
257
|
+
}
|
|
258
|
+
var adaptViemWallet = (wallet) => {
|
|
259
|
+
const signTypedData = async (signData) => {
|
|
260
|
+
return await wallet.signTypedData({
|
|
261
|
+
account: wallet.account,
|
|
262
|
+
domain: signData.domain,
|
|
263
|
+
types: signData.types,
|
|
264
|
+
primaryType: signData.primaryType ?? "Order",
|
|
265
|
+
message: signData.value
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
const sendTransaction = async (transaction) => {
|
|
269
|
+
if (!isEVMTransaction(transaction)) {
|
|
270
|
+
throw new Error("Expected EVMTransaction but got SolanaTransaction");
|
|
271
|
+
}
|
|
272
|
+
const tx = await wallet.sendTransaction({
|
|
273
|
+
from: transaction.from,
|
|
274
|
+
to: transaction.to,
|
|
275
|
+
data: transaction.data,
|
|
276
|
+
value: transaction.value,
|
|
277
|
+
account: wallet.account?.address,
|
|
278
|
+
chain: wallet.chain
|
|
279
|
+
});
|
|
280
|
+
return tx;
|
|
281
|
+
};
|
|
282
|
+
const switchChain = async (chainId) => {
|
|
283
|
+
try {
|
|
284
|
+
await wallet.switchChain({ id: chainId });
|
|
285
|
+
} catch (e) {
|
|
286
|
+
const msg = e?.message || "";
|
|
287
|
+
if (msg.includes("does not support the requested chain")) {
|
|
288
|
+
throw new Error("Wallet does not support this chain");
|
|
289
|
+
}
|
|
290
|
+
if (msg.includes("rejected")) throw e;
|
|
291
|
+
if (msg.includes("already pending")) return;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
const address = async () => {
|
|
295
|
+
let addr = wallet.account?.address;
|
|
296
|
+
if (!addr) {
|
|
297
|
+
const addresses = await wallet.getAddresses();
|
|
298
|
+
addr = addresses[0];
|
|
299
|
+
}
|
|
300
|
+
if (!addr) throw new Error("No address found");
|
|
301
|
+
return addr;
|
|
302
|
+
};
|
|
303
|
+
return {
|
|
304
|
+
vmType: "EVM" /* EVM */,
|
|
305
|
+
transport: custom(wallet.transport),
|
|
306
|
+
getChainId: async () => wallet.getChainId(),
|
|
307
|
+
address,
|
|
308
|
+
sendTransaction,
|
|
309
|
+
signTypedData,
|
|
310
|
+
switchChain
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/core/executeOrder/handleEvmExecution.ts
|
|
315
|
+
import {
|
|
316
|
+
getEVMSingleChainOrderTypedData,
|
|
317
|
+
getEVMCrossChainOrderTypedData,
|
|
318
|
+
PERMIT2_ADDRESS
|
|
319
|
+
} from "@shogun-sdk/intents-sdk";
|
|
320
|
+
import { encodeFunctionData, erc20Abi } from "viem";
|
|
321
|
+
|
|
322
|
+
// src/core/executeOrder/stageMessages.ts
|
|
323
|
+
var DEFAULT_STAGE_MESSAGES = {
|
|
324
|
+
processing: "Preparing transaction for execution",
|
|
325
|
+
approving: "Approving token allowance",
|
|
326
|
+
approved: "Token approved successfully",
|
|
327
|
+
signing: "Signing order for submission",
|
|
328
|
+
submitting: "Submitting order to Auctioneer",
|
|
329
|
+
success: "Order executed successfully",
|
|
330
|
+
error: "Order execution failed"
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// src/core/executeOrder/buildOrder.ts
|
|
334
|
+
import { CrossChainOrder, SingleChainOrder } from "@shogun-sdk/intents-sdk";
|
|
335
|
+
async function buildOrder({
|
|
336
|
+
quote,
|
|
337
|
+
accountAddress,
|
|
338
|
+
destination,
|
|
339
|
+
deadline,
|
|
340
|
+
isSingleChain
|
|
341
|
+
}) {
|
|
342
|
+
const { tokenIn, tokenOut } = quote;
|
|
343
|
+
if (isSingleChain) {
|
|
344
|
+
return await SingleChainOrder.create({
|
|
345
|
+
user: accountAddress,
|
|
346
|
+
chainId: tokenIn.chainId,
|
|
347
|
+
tokenIn: tokenIn.address,
|
|
348
|
+
tokenOut: tokenOut.address,
|
|
349
|
+
amountIn: quote.amountIn,
|
|
350
|
+
amountOutMin: quote.internal.estimatedAmountOutReduced,
|
|
351
|
+
deadline,
|
|
352
|
+
destinationAddress: destination
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return await CrossChainOrder.create({
|
|
356
|
+
user: accountAddress,
|
|
357
|
+
sourceChainId: tokenIn.chainId,
|
|
358
|
+
sourceTokenAddress: tokenIn.address,
|
|
359
|
+
sourceTokenAmount: quote.amountIn,
|
|
360
|
+
destinationChainId: tokenOut.chainId,
|
|
361
|
+
destinationTokenAddress: tokenOut.address,
|
|
362
|
+
destinationAddress: destination,
|
|
363
|
+
deadline,
|
|
364
|
+
destinationTokenMinAmount: quote.internal.estimatedAmountOutReduced,
|
|
365
|
+
minStablecoinAmount: quote.minStablecoinsAmount
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/core/executeOrder/handleEvmExecution.ts
|
|
370
|
+
async function handleEvmExecution({
|
|
371
|
+
recipientAddress,
|
|
372
|
+
quote,
|
|
373
|
+
chainId,
|
|
374
|
+
accountAddress,
|
|
375
|
+
wallet,
|
|
376
|
+
isSingleChain,
|
|
377
|
+
deadline,
|
|
378
|
+
update
|
|
379
|
+
}) {
|
|
380
|
+
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
|
|
381
|
+
await wallet.switchChain(chainId);
|
|
382
|
+
const tokenIn = normalizeNative(chainId, quote.tokenIn.address);
|
|
383
|
+
const shouldWrapNative = isNativeAddress(quote.tokenIn.address);
|
|
384
|
+
update("processing", shouldWrapNative ? `${messageFor("processing")} (wrapping native token)` : messageFor("processing"));
|
|
385
|
+
if (shouldWrapNative) {
|
|
386
|
+
await wallet.sendTransaction({
|
|
387
|
+
to: tokenIn,
|
|
388
|
+
data: encodeFunctionData({
|
|
389
|
+
abi: [{ type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] }],
|
|
390
|
+
functionName: "deposit",
|
|
391
|
+
args: []
|
|
392
|
+
}),
|
|
393
|
+
value: BigInt(quote.amountIn),
|
|
394
|
+
from: accountAddress
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
update("approving", messageFor("approving"));
|
|
398
|
+
await wallet.sendTransaction({
|
|
399
|
+
to: tokenIn,
|
|
400
|
+
data: encodeFunctionData({
|
|
401
|
+
abi: erc20Abi,
|
|
402
|
+
functionName: "approve",
|
|
403
|
+
args: [PERMIT2_ADDRESS[chainId], BigInt(quote.amountIn)]
|
|
404
|
+
}),
|
|
405
|
+
value: 0n,
|
|
406
|
+
from: accountAddress
|
|
407
|
+
});
|
|
408
|
+
update("approved", messageFor("approved"));
|
|
409
|
+
const destination = recipientAddress ?? accountAddress;
|
|
410
|
+
const order = await buildOrder({
|
|
411
|
+
quote,
|
|
412
|
+
accountAddress,
|
|
413
|
+
destination,
|
|
414
|
+
deadline,
|
|
415
|
+
isSingleChain
|
|
416
|
+
});
|
|
417
|
+
update("signing", messageFor("signing"));
|
|
418
|
+
const { orderTypedData, nonce } = isSingleChain ? await getEVMSingleChainOrderTypedData(order) : await getEVMCrossChainOrderTypedData(order);
|
|
419
|
+
if (!wallet.signTypedData) {
|
|
420
|
+
throw new Error("Wallet does not support EIP-712 signing");
|
|
421
|
+
}
|
|
422
|
+
const signature = await wallet.signTypedData(serializeBigIntsToStrings(orderTypedData));
|
|
423
|
+
update("submitting", messageFor("submitting"));
|
|
424
|
+
const res = await order.sendToAuctioneer({ signature, nonce: nonce.toString() });
|
|
425
|
+
if (!res.success) {
|
|
426
|
+
throw new Error("Auctioneer submission failed");
|
|
427
|
+
}
|
|
428
|
+
update("success", messageFor("success"));
|
|
429
|
+
return { status: true, txHash: res.data, chainId, stage: "success" };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/core/executeOrder/handleSolanaExecution.ts
|
|
433
|
+
import {
|
|
434
|
+
ChainID as ChainID3,
|
|
435
|
+
getSolanaSingleChainOrderInstructions,
|
|
436
|
+
getSolanaCrossChainOrderInstructions
|
|
437
|
+
} from "@shogun-sdk/intents-sdk";
|
|
438
|
+
import { VersionedTransaction } from "@solana/web3.js";
|
|
439
|
+
async function handleSolanaExecution({
|
|
440
|
+
recipientAddress,
|
|
441
|
+
quote,
|
|
442
|
+
wallet,
|
|
443
|
+
isSingleChain,
|
|
444
|
+
update,
|
|
445
|
+
accountAddress,
|
|
446
|
+
deadline
|
|
447
|
+
}) {
|
|
448
|
+
if (!wallet.rpcUrl) {
|
|
449
|
+
throw new Error("Solana wallet is missing rpcUrl");
|
|
450
|
+
}
|
|
451
|
+
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
|
|
452
|
+
update("processing", messageFor("processing"));
|
|
453
|
+
const destination = recipientAddress ?? accountAddress;
|
|
454
|
+
const order = await buildOrder({
|
|
455
|
+
quote,
|
|
456
|
+
accountAddress,
|
|
457
|
+
destination,
|
|
458
|
+
deadline,
|
|
459
|
+
isSingleChain
|
|
460
|
+
});
|
|
461
|
+
const txData = await getSolanaOrderInstructions({
|
|
462
|
+
order,
|
|
463
|
+
isSingleChain,
|
|
464
|
+
rpcUrl: wallet.rpcUrl
|
|
465
|
+
});
|
|
466
|
+
const transaction = VersionedTransaction.deserialize(Uint8Array.from(txData.txBytes));
|
|
467
|
+
update("signing", messageFor("signing"));
|
|
468
|
+
console.log({ order });
|
|
469
|
+
const txSignature = await wallet.sendTransaction(transaction);
|
|
470
|
+
update("submitting", messageFor("submitting"));
|
|
471
|
+
const response = await submitToAuctioneer({
|
|
472
|
+
order,
|
|
473
|
+
isSingleChain,
|
|
474
|
+
txData
|
|
475
|
+
});
|
|
476
|
+
if (!response.success) {
|
|
477
|
+
throw new Error("Auctioneer submission failed");
|
|
478
|
+
}
|
|
479
|
+
update("success", messageFor("success"));
|
|
480
|
+
return {
|
|
481
|
+
status: true,
|
|
482
|
+
txHash: txSignature,
|
|
483
|
+
chainId: ChainID3.Solana,
|
|
484
|
+
stage: "success"
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
async function getSolanaOrderInstructions({
|
|
488
|
+
order,
|
|
489
|
+
isSingleChain,
|
|
490
|
+
rpcUrl
|
|
491
|
+
}) {
|
|
492
|
+
if (isSingleChain) {
|
|
493
|
+
return await getSolanaSingleChainOrderInstructions(order, {
|
|
494
|
+
rpcUrl
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
return await getSolanaCrossChainOrderInstructions(order, {
|
|
498
|
+
rpcUrl
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
async function submitToAuctioneer({
|
|
502
|
+
order,
|
|
503
|
+
isSingleChain,
|
|
504
|
+
txData
|
|
505
|
+
}) {
|
|
506
|
+
if (isSingleChain) {
|
|
507
|
+
const { orderAddress, secretNumber } = txData;
|
|
508
|
+
return await order.sendToAuctioneer({
|
|
509
|
+
orderPubkey: orderAddress,
|
|
510
|
+
secretNumber
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
return await order.sendToAuctioneer({
|
|
514
|
+
orderPubkey: txData.orderAddress
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// src/core/executeOrder/execute.ts
|
|
519
|
+
async function executeOrder({
|
|
520
|
+
quote,
|
|
521
|
+
accountAddress,
|
|
522
|
+
recipientAddress,
|
|
523
|
+
wallet,
|
|
524
|
+
onStatus,
|
|
525
|
+
options = {}
|
|
526
|
+
}) {
|
|
527
|
+
const deadline = options.deadline ?? Math.floor(Date.now() / 1e3) + 20 * 60;
|
|
528
|
+
const messageFor = (stage) => DEFAULT_STAGE_MESSAGES[stage];
|
|
529
|
+
const update = (stage, message) => onStatus?.(stage, message ?? messageFor(stage));
|
|
530
|
+
try {
|
|
531
|
+
const adapter = normalizeWallet(wallet);
|
|
532
|
+
if (!adapter) throw new Error("No wallet provided");
|
|
533
|
+
const { tokenIn, tokenOut } = quote;
|
|
534
|
+
const isSingleChain = tokenIn.chainId === tokenOut.chainId;
|
|
535
|
+
const chainId = Number(tokenIn.chainId);
|
|
536
|
+
update("processing", messageFor("processing"));
|
|
537
|
+
if (isEvmChain2(chainId)) {
|
|
538
|
+
return await handleEvmExecution({
|
|
539
|
+
recipientAddress,
|
|
540
|
+
quote,
|
|
541
|
+
chainId,
|
|
542
|
+
accountAddress,
|
|
543
|
+
wallet: adapter,
|
|
544
|
+
isSingleChain,
|
|
545
|
+
deadline,
|
|
546
|
+
update
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
if (chainId === ChainID4.Solana) {
|
|
550
|
+
return await handleSolanaExecution({
|
|
551
|
+
recipientAddress,
|
|
552
|
+
quote,
|
|
553
|
+
accountAddress,
|
|
554
|
+
wallet: adapter,
|
|
555
|
+
isSingleChain,
|
|
556
|
+
deadline,
|
|
557
|
+
update
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
update("error", "Unsupported chain");
|
|
561
|
+
return { status: false, message: "Unsupported chain", stage: "error" };
|
|
562
|
+
} catch (error) {
|
|
563
|
+
const message = error instanceof BaseError ? error.shortMessage : error instanceof Error ? error.message : String(error);
|
|
564
|
+
update("error", message);
|
|
565
|
+
return { status: false, message, stage: "error" };
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function normalizeWallet(wallet) {
|
|
569
|
+
if (!wallet) return void 0;
|
|
570
|
+
if (isViemWalletClient(wallet)) return adaptViemWallet(wallet);
|
|
571
|
+
return wallet;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/core/index.ts
|
|
575
|
+
import { ChainID as ChainID5, isEvmChain as isEvmChain3 } from "@shogun-sdk/intents-sdk";
|
|
576
|
+
export {
|
|
577
|
+
ChainID5 as ChainID,
|
|
578
|
+
NATIVE_TOKEN,
|
|
579
|
+
SOLANA_CHAIN_ID,
|
|
580
|
+
SupportedChains,
|
|
581
|
+
buildQuoteParams,
|
|
582
|
+
executeOrder,
|
|
583
|
+
getBalances,
|
|
584
|
+
getQuote,
|
|
585
|
+
getTokenList,
|
|
586
|
+
isEvmChain3 as isEvmChain,
|
|
587
|
+
isNativeAddress,
|
|
588
|
+
isViemWalletClient,
|
|
589
|
+
serializeBigIntsToStrings
|
|
590
|
+
};
|