@tokenflight/swap 0.0.0 → 0.0.1
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 +9 -0
- package/dist/index.d.ts +27 -23
- package/dist/tokenflight-swap.css +1 -1
- package/dist/tokenflight-swap.js +1072 -1114
- package/dist/tokenflight-swap.umd.cjs +3 -3
- package/package.json +2 -10
package/dist/tokenflight-swap.js
CHANGED
|
@@ -8364,267 +8364,135 @@ function RecipientEditor(props) {
|
|
|
8364
8364
|
return _el$;
|
|
8365
8365
|
})();
|
|
8366
8366
|
}
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
}
|
|
8395
|
-
function
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
`[TokenFlight] Invalid state transition: ${current} → ${nextPhase}`
|
|
8401
|
-
);
|
|
8402
|
-
return false;
|
|
8403
|
-
}
|
|
8404
|
-
setState((prev) => ({ ...prev, phase: nextPhase }));
|
|
8405
|
-
return true;
|
|
8406
|
-
}
|
|
8407
|
-
function setFromToken(token) {
|
|
8408
|
-
setState((prev) => ({ ...prev, fromToken: token }));
|
|
8409
|
-
}
|
|
8410
|
-
function setToToken(token) {
|
|
8411
|
-
setState((prev) => ({ ...prev, toToken: token }));
|
|
8412
|
-
}
|
|
8413
|
-
function setInputAmount(amount2) {
|
|
8414
|
-
setState((prev) => ({ ...prev, inputAmount: amount2 }));
|
|
8415
|
-
}
|
|
8416
|
-
function setOutputAmount(amount2) {
|
|
8417
|
-
setState((prev) => ({ ...prev, outputAmount: amount2 }));
|
|
8418
|
-
}
|
|
8419
|
-
function setQuoteData(quoteId, routes, selectedRouteId) {
|
|
8367
|
+
function deriveSwapPhase(execPhase, error2, isFetching, routeCount, hasQuoteRequest) {
|
|
8368
|
+
if (execPhase) return execPhase;
|
|
8369
|
+
if (error2) return "error";
|
|
8370
|
+
if (isFetching && routeCount === 0 && hasQuoteRequest) return "quoting";
|
|
8371
|
+
if (routeCount > 0) return "quoted";
|
|
8372
|
+
return "idle";
|
|
8373
|
+
}
|
|
8374
|
+
function deriveReceivePhase(execPhase, error2, loadingQuotes, quoteCount) {
|
|
8375
|
+
if (execPhase) return execPhase;
|
|
8376
|
+
if (error2) return "error";
|
|
8377
|
+
if (loadingQuotes && quoteCount === 0) return "quoting";
|
|
8378
|
+
if (quoteCount > 0) return "quoted";
|
|
8379
|
+
return "idle";
|
|
8380
|
+
}
|
|
8381
|
+
function createSwapStore() {
|
|
8382
|
+
const [fromToken, setFromToken] = createSignal(null);
|
|
8383
|
+
const [toToken, setToToken] = createSignal(null);
|
|
8384
|
+
const [inputAmount, setInputAmount] = createSignal("");
|
|
8385
|
+
const [recipient, _setRecipient] = createSignal(null);
|
|
8386
|
+
const [walletAddress2, _setWalletAddress] = createSignal(null);
|
|
8387
|
+
const [execPhase, setExecPhase] = createSignal(null);
|
|
8388
|
+
const [order, setOrder] = createSignal(null);
|
|
8389
|
+
const [error2, setError] = createSignal(null);
|
|
8390
|
+
const [errorCode, setErrorCode] = createSignal(null);
|
|
8391
|
+
function setWalletAddress(addr) {
|
|
8392
|
+
if (walletAddress2() === addr) return;
|
|
8393
|
+
_setWalletAddress(addr);
|
|
8394
|
+
}
|
|
8395
|
+
function setRecipient(r) {
|
|
8396
|
+
if (recipient() === r) return;
|
|
8397
|
+
_setRecipient(r);
|
|
8398
|
+
}
|
|
8399
|
+
function clearError() {
|
|
8420
8400
|
batch(() => {
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
quoteId,
|
|
8424
|
-
routes,
|
|
8425
|
-
selectedRouteId
|
|
8426
|
-
}));
|
|
8427
|
-
});
|
|
8428
|
-
}
|
|
8429
|
-
function addStreamingRoute(quoteId, route) {
|
|
8430
|
-
setState((prev) => {
|
|
8431
|
-
if (prev.routes.some((r) => r.routeId === route.routeId)) {
|
|
8432
|
-
return { ...prev, quoteId };
|
|
8433
|
-
}
|
|
8434
|
-
return { ...prev, quoteId, routes: [...prev.routes, route] };
|
|
8401
|
+
setError(null);
|
|
8402
|
+
setErrorCode(null);
|
|
8435
8403
|
});
|
|
8436
8404
|
}
|
|
8437
|
-
function clearRoutes() {
|
|
8438
|
-
setState((prev) => ({
|
|
8439
|
-
...prev,
|
|
8440
|
-
routes: [],
|
|
8441
|
-
quoteId: null,
|
|
8442
|
-
selectedRouteId: null
|
|
8443
|
-
}));
|
|
8444
|
-
}
|
|
8445
|
-
function setSelectedRouteId(routeId) {
|
|
8446
|
-
setState((prev) => ({ ...prev, selectedRouteId: routeId }));
|
|
8447
|
-
}
|
|
8448
|
-
function setStreaming(isStreaming) {
|
|
8449
|
-
setState((prev) => ({ ...prev, isStreaming }));
|
|
8450
|
-
}
|
|
8451
|
-
function setOrder(order) {
|
|
8452
|
-
setState((prev) => ({ ...prev, order }));
|
|
8453
|
-
}
|
|
8454
|
-
function setWalletAddress(address) {
|
|
8455
|
-
if (state().walletAddress === address) return;
|
|
8456
|
-
setState((prev) => ({ ...prev, walletAddress: address }));
|
|
8457
|
-
}
|
|
8458
|
-
function setError(error2, errorCode = null) {
|
|
8459
|
-
const current = state().phase;
|
|
8460
|
-
const allowed = VALID_TRANSITIONS[current];
|
|
8461
|
-
if (allowed?.includes("error")) {
|
|
8462
|
-
setState((prev) => ({ ...prev, error: error2, errorCode, phase: "error" }));
|
|
8463
|
-
} else {
|
|
8464
|
-
setState((prev) => ({ ...prev, error: error2, errorCode }));
|
|
8465
|
-
}
|
|
8466
|
-
}
|
|
8467
|
-
function setRecipient(recipient) {
|
|
8468
|
-
if (state().recipient === recipient) return;
|
|
8469
|
-
setState((prev) => ({ ...prev, recipient }));
|
|
8470
|
-
}
|
|
8471
8405
|
function reset() {
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
selectedRouteId: null,
|
|
8480
|
-
order: null,
|
|
8481
|
-
isStreaming: false,
|
|
8482
|
-
error: null,
|
|
8483
|
-
errorCode: null
|
|
8484
|
-
}));
|
|
8406
|
+
batch(() => {
|
|
8407
|
+
setInputAmount("");
|
|
8408
|
+
setOrder(null);
|
|
8409
|
+
setExecPhase(null);
|
|
8410
|
+
setError(null);
|
|
8411
|
+
setErrorCode(null);
|
|
8412
|
+
});
|
|
8485
8413
|
}
|
|
8486
8414
|
return {
|
|
8487
|
-
|
|
8488
|
-
|
|
8415
|
+
// Accessors
|
|
8416
|
+
fromToken,
|
|
8417
|
+
toToken,
|
|
8418
|
+
inputAmount,
|
|
8419
|
+
recipient,
|
|
8420
|
+
walletAddress: walletAddress2,
|
|
8421
|
+
execPhase,
|
|
8422
|
+
order,
|
|
8423
|
+
error: error2,
|
|
8424
|
+
errorCode,
|
|
8425
|
+
// Setters
|
|
8489
8426
|
setFromToken,
|
|
8490
8427
|
setToToken,
|
|
8491
8428
|
setInputAmount,
|
|
8492
|
-
|
|
8493
|
-
setQuoteData,
|
|
8494
|
-
addStreamingRoute,
|
|
8495
|
-
clearRoutes,
|
|
8496
|
-
setSelectedRouteId,
|
|
8497
|
-
setStreaming,
|
|
8498
|
-
setOrder,
|
|
8429
|
+
setRecipient,
|
|
8499
8430
|
setWalletAddress,
|
|
8431
|
+
setExecPhase,
|
|
8432
|
+
setOrder,
|
|
8500
8433
|
setError,
|
|
8501
|
-
|
|
8434
|
+
setErrorCode,
|
|
8435
|
+
// Batch helpers
|
|
8436
|
+
clearError,
|
|
8502
8437
|
reset
|
|
8503
8438
|
};
|
|
8504
8439
|
}
|
|
8505
|
-
function
|
|
8506
|
-
const [
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
recipient
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
const allowed = VALID_TRANSITIONS[current];
|
|
8525
|
-
if (!allowed?.includes(nextPhase)) {
|
|
8526
|
-
console.warn(
|
|
8527
|
-
`[TokenFlight] Invalid state transition: ${current} → ${nextPhase}`
|
|
8528
|
-
);
|
|
8529
|
-
return false;
|
|
8530
|
-
}
|
|
8531
|
-
setState((prev) => ({ ...prev, phase: nextPhase }));
|
|
8532
|
-
return true;
|
|
8533
|
-
}
|
|
8534
|
-
function setTargetToken(token) {
|
|
8535
|
-
setState((prev) => ({ ...prev, targetToken: token }));
|
|
8536
|
-
}
|
|
8537
|
-
function setFromToken(token) {
|
|
8538
|
-
setState((prev) => ({ ...prev, fromToken: token }));
|
|
8539
|
-
}
|
|
8540
|
-
function setTargetAmount(amount2) {
|
|
8541
|
-
setState((prev) => ({ ...prev, targetAmount: amount2 }));
|
|
8542
|
-
}
|
|
8543
|
-
function setPaymentAmount(amount2) {
|
|
8544
|
-
setState((prev) => ({ ...prev, paymentAmount: amount2 }));
|
|
8545
|
-
}
|
|
8546
|
-
function setQuoteData(quoteId, routes, selectedRouteId) {
|
|
8440
|
+
function createReceiveStore() {
|
|
8441
|
+
const [targetToken, setTargetToken] = createSignal(null);
|
|
8442
|
+
const [targetAmount, setTargetAmount] = createSignal("");
|
|
8443
|
+
const [fromToken, setFromToken] = createSignal(null);
|
|
8444
|
+
const [recipient, _setRecipient] = createSignal(null);
|
|
8445
|
+
const [walletAddress2, _setWalletAddress] = createSignal(null);
|
|
8446
|
+
const [execPhase, setExecPhase] = createSignal(null);
|
|
8447
|
+
const [order, setOrder] = createSignal(null);
|
|
8448
|
+
const [error2, setError] = createSignal(null);
|
|
8449
|
+
const [errorCode, setErrorCode] = createSignal(null);
|
|
8450
|
+
function setWalletAddress(addr) {
|
|
8451
|
+
if (walletAddress2() === addr) return;
|
|
8452
|
+
_setWalletAddress(addr);
|
|
8453
|
+
}
|
|
8454
|
+
function setRecipient(r) {
|
|
8455
|
+
if (recipient() === r) return;
|
|
8456
|
+
_setRecipient(r);
|
|
8457
|
+
}
|
|
8458
|
+
function clearError() {
|
|
8547
8459
|
batch(() => {
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
quoteId,
|
|
8551
|
-
routes,
|
|
8552
|
-
selectedRouteId
|
|
8553
|
-
}));
|
|
8554
|
-
});
|
|
8555
|
-
}
|
|
8556
|
-
function addStreamingRoute(quoteId, route) {
|
|
8557
|
-
setState((prev) => {
|
|
8558
|
-
if (prev.routes.some((r) => r.routeId === route.routeId)) {
|
|
8559
|
-
return { ...prev, quoteId };
|
|
8560
|
-
}
|
|
8561
|
-
return { ...prev, quoteId, routes: [...prev.routes, route] };
|
|
8460
|
+
setError(null);
|
|
8461
|
+
setErrorCode(null);
|
|
8562
8462
|
});
|
|
8563
8463
|
}
|
|
8564
|
-
function clearRoutes() {
|
|
8565
|
-
setState((prev) => ({
|
|
8566
|
-
...prev,
|
|
8567
|
-
routes: [],
|
|
8568
|
-
quoteId: null,
|
|
8569
|
-
selectedRouteId: null
|
|
8570
|
-
}));
|
|
8571
|
-
}
|
|
8572
|
-
function setSelectedRouteId(routeId) {
|
|
8573
|
-
setState((prev) => ({ ...prev, selectedRouteId: routeId }));
|
|
8574
|
-
}
|
|
8575
|
-
function setStreaming(isStreaming) {
|
|
8576
|
-
setState((prev) => ({ ...prev, isStreaming }));
|
|
8577
|
-
}
|
|
8578
|
-
function setOrder(order) {
|
|
8579
|
-
setState((prev) => ({ ...prev, order }));
|
|
8580
|
-
}
|
|
8581
|
-
function setWalletAddress(address) {
|
|
8582
|
-
if (state().walletAddress === address) return;
|
|
8583
|
-
setState((prev) => ({ ...prev, walletAddress: address }));
|
|
8584
|
-
}
|
|
8585
|
-
function setRecipient(recipient) {
|
|
8586
|
-
if (state().recipient === recipient) return;
|
|
8587
|
-
setState((prev) => ({ ...prev, recipient }));
|
|
8588
|
-
}
|
|
8589
|
-
function setError(error2, errorCode = null) {
|
|
8590
|
-
const current = state().phase;
|
|
8591
|
-
const allowed = VALID_TRANSITIONS[current];
|
|
8592
|
-
if (allowed?.includes("error")) {
|
|
8593
|
-
setState((prev) => ({ ...prev, error: error2, errorCode, phase: "error" }));
|
|
8594
|
-
} else {
|
|
8595
|
-
setState((prev) => ({ ...prev, error: error2, errorCode }));
|
|
8596
|
-
}
|
|
8597
|
-
}
|
|
8598
8464
|
function reset() {
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
error: null,
|
|
8607
|
-
errorCode: null,
|
|
8608
|
-
paymentAmount: "",
|
|
8609
|
-
isStreaming: false
|
|
8610
|
-
}));
|
|
8465
|
+
batch(() => {
|
|
8466
|
+
setFromToken(null);
|
|
8467
|
+
setOrder(null);
|
|
8468
|
+
setExecPhase(null);
|
|
8469
|
+
setError(null);
|
|
8470
|
+
setErrorCode(null);
|
|
8471
|
+
});
|
|
8611
8472
|
}
|
|
8612
8473
|
return {
|
|
8613
|
-
|
|
8614
|
-
|
|
8474
|
+
// Accessors
|
|
8475
|
+
targetToken,
|
|
8476
|
+
targetAmount,
|
|
8477
|
+
fromToken,
|
|
8478
|
+
recipient,
|
|
8479
|
+
walletAddress: walletAddress2,
|
|
8480
|
+
execPhase,
|
|
8481
|
+
order,
|
|
8482
|
+
error: error2,
|
|
8483
|
+
errorCode,
|
|
8484
|
+
// Setters
|
|
8615
8485
|
setTargetToken,
|
|
8616
|
-
setFromToken,
|
|
8617
8486
|
setTargetAmount,
|
|
8618
|
-
|
|
8619
|
-
setQuoteData,
|
|
8620
|
-
addStreamingRoute,
|
|
8621
|
-
clearRoutes,
|
|
8622
|
-
setSelectedRouteId,
|
|
8623
|
-
setStreaming,
|
|
8624
|
-
setOrder,
|
|
8625
|
-
setWalletAddress,
|
|
8487
|
+
setFromToken,
|
|
8626
8488
|
setRecipient,
|
|
8489
|
+
setWalletAddress,
|
|
8490
|
+
setExecPhase,
|
|
8491
|
+
setOrder,
|
|
8627
8492
|
setError,
|
|
8493
|
+
setErrorCode,
|
|
8494
|
+
// Batch helpers
|
|
8495
|
+
clearError,
|
|
8628
8496
|
reset
|
|
8629
8497
|
};
|
|
8630
8498
|
}
|
|
@@ -8820,6 +8688,320 @@ function getBestOverallRouteId(routes, tradeType) {
|
|
|
8820
8688
|
const ranked = rankOffers(offers);
|
|
8821
8689
|
return ranked[0] ?? null;
|
|
8822
8690
|
}
|
|
8691
|
+
function useWalletConnection(params) {
|
|
8692
|
+
const [isConnected, setIsConnected] = createSignal(false);
|
|
8693
|
+
const [walletAddress2, setWalletAddress] = createSignal(null);
|
|
8694
|
+
const detectChainType = () => {
|
|
8695
|
+
const adapter = params.walletAdapter();
|
|
8696
|
+
if (!adapter) return "evm";
|
|
8697
|
+
return adapter.supportedActionTypes.some((t2) => t2.startsWith("solana_")) ? "solana" : "evm";
|
|
8698
|
+
};
|
|
8699
|
+
onMount(async () => {
|
|
8700
|
+
const adapter = params.walletAdapter();
|
|
8701
|
+
if (!adapter) return;
|
|
8702
|
+
const connected = adapter.isConnected();
|
|
8703
|
+
setIsConnected(connected);
|
|
8704
|
+
if (connected) {
|
|
8705
|
+
const addr = await adapter.getAddress();
|
|
8706
|
+
setWalletAddress(addr);
|
|
8707
|
+
params.onAddressChange(addr);
|
|
8708
|
+
params.callbacks()?.onWalletConnected?.({
|
|
8709
|
+
address: addr ?? "",
|
|
8710
|
+
chainType: detectChainType()
|
|
8711
|
+
});
|
|
8712
|
+
}
|
|
8713
|
+
const handleWalletConnect = async () => {
|
|
8714
|
+
const addr = await adapter.getAddress();
|
|
8715
|
+
if (isConnected() && walletAddress2() === addr) return;
|
|
8716
|
+
batch(() => {
|
|
8717
|
+
setIsConnected(true);
|
|
8718
|
+
setWalletAddress(addr);
|
|
8719
|
+
params.onAddressChange(addr);
|
|
8720
|
+
});
|
|
8721
|
+
params.callbacks()?.onWalletConnected?.({
|
|
8722
|
+
address: addr ?? "",
|
|
8723
|
+
chainType: detectChainType()
|
|
8724
|
+
});
|
|
8725
|
+
};
|
|
8726
|
+
const handleWalletDisconnect = () => {
|
|
8727
|
+
if (!isConnected()) return;
|
|
8728
|
+
batch(() => {
|
|
8729
|
+
setIsConnected(false);
|
|
8730
|
+
setWalletAddress(null);
|
|
8731
|
+
params.onAddressChange(null);
|
|
8732
|
+
});
|
|
8733
|
+
params.onDisconnect?.();
|
|
8734
|
+
};
|
|
8735
|
+
adapter.on("connect", handleWalletConnect);
|
|
8736
|
+
adapter.on("disconnect", handleWalletDisconnect);
|
|
8737
|
+
onCleanup(() => {
|
|
8738
|
+
adapter.off("connect", handleWalletConnect);
|
|
8739
|
+
adapter.off("disconnect", handleWalletDisconnect);
|
|
8740
|
+
});
|
|
8741
|
+
});
|
|
8742
|
+
const handleConnect = async () => {
|
|
8743
|
+
const adapter = params.walletAdapter();
|
|
8744
|
+
if (!adapter) {
|
|
8745
|
+
console.warn(
|
|
8746
|
+
"[TokenFlight] No wallet adapter configured. Pass a walletAdapter to enable wallet connection.\nSee: https://embed.tokenflight.ai/guides/wallet-adapter/"
|
|
8747
|
+
);
|
|
8748
|
+
params.callbacks()?.onConnectWallet?.();
|
|
8749
|
+
return;
|
|
8750
|
+
}
|
|
8751
|
+
try {
|
|
8752
|
+
await adapter.connect();
|
|
8753
|
+
} catch {
|
|
8754
|
+
params.onConnectError?.(
|
|
8755
|
+
"Failed to connect wallet",
|
|
8756
|
+
ErrorCode.WALLET_CONNECTION_FAILED
|
|
8757
|
+
);
|
|
8758
|
+
}
|
|
8759
|
+
};
|
|
8760
|
+
return {
|
|
8761
|
+
isConnected,
|
|
8762
|
+
walletAddress: walletAddress2,
|
|
8763
|
+
detectChainType,
|
|
8764
|
+
handleConnect
|
|
8765
|
+
};
|
|
8766
|
+
}
|
|
8767
|
+
function useQuoteCountdown(params) {
|
|
8768
|
+
const interval = params.intervalSeconds ?? QUOTE_REFRESH_SECONDS;
|
|
8769
|
+
const [countdownSeconds, setCountdownSeconds] = createSignal(interval);
|
|
8770
|
+
createEffect(
|
|
8771
|
+
on(params.phase, (p) => {
|
|
8772
|
+
if (p !== "quoted") {
|
|
8773
|
+
setCountdownSeconds(interval);
|
|
8774
|
+
return;
|
|
8775
|
+
}
|
|
8776
|
+
setCountdownSeconds(interval);
|
|
8777
|
+
const timer = setInterval(() => {
|
|
8778
|
+
setCountdownSeconds((prev) => {
|
|
8779
|
+
if (prev <= 1) {
|
|
8780
|
+
params.onExpired();
|
|
8781
|
+
return interval;
|
|
8782
|
+
}
|
|
8783
|
+
return prev - 1;
|
|
8784
|
+
});
|
|
8785
|
+
}, 1e3);
|
|
8786
|
+
onCleanup(() => clearInterval(timer));
|
|
8787
|
+
})
|
|
8788
|
+
);
|
|
8789
|
+
return { countdownSeconds };
|
|
8790
|
+
}
|
|
8791
|
+
function useRecipient(params) {
|
|
8792
|
+
const needRecipient = createMemo(() => {
|
|
8793
|
+
const from = params.fromToken();
|
|
8794
|
+
const to = params.toToken();
|
|
8795
|
+
if (!from || !to || !params.isConnected()) return false;
|
|
8796
|
+
return isCrossChainSwap(from.chainId, to.chainId);
|
|
8797
|
+
});
|
|
8798
|
+
const recipientDisplay = createMemo(() => {
|
|
8799
|
+
const r = params.recipient();
|
|
8800
|
+
if (r) return r;
|
|
8801
|
+
if (params.isConnected() && params.walletAddress() && !needRecipient())
|
|
8802
|
+
return params.walletAddress();
|
|
8803
|
+
return null;
|
|
8804
|
+
});
|
|
8805
|
+
createEffect(
|
|
8806
|
+
on(needRecipient, (need) => {
|
|
8807
|
+
if (need && !params.recipient() && params.walletAdapter()) {
|
|
8808
|
+
const to = params.toToken();
|
|
8809
|
+
if (!to) return;
|
|
8810
|
+
const targetChainType = getChainType(to.chainId);
|
|
8811
|
+
params.walletAdapter().getAddress(targetChainType).then((addr) => {
|
|
8812
|
+
if (addr && isAddressForChainType(addr, targetChainType) && !params.recipient() && needRecipient()) {
|
|
8813
|
+
params.setRecipient(addr);
|
|
8814
|
+
}
|
|
8815
|
+
}).catch(() => {
|
|
8816
|
+
});
|
|
8817
|
+
}
|
|
8818
|
+
})
|
|
8819
|
+
);
|
|
8820
|
+
const handleRecipientChange = (value2) => {
|
|
8821
|
+
params.setRecipient(value2.trim() || null);
|
|
8822
|
+
};
|
|
8823
|
+
return {
|
|
8824
|
+
needRecipient,
|
|
8825
|
+
recipientDisplay,
|
|
8826
|
+
handleRecipientChange
|
|
8827
|
+
};
|
|
8828
|
+
}
|
|
8829
|
+
function useOrderTracking(params) {
|
|
8830
|
+
const orderQuery = createOrderQuery(
|
|
8831
|
+
params.client,
|
|
8832
|
+
params.walletAddress,
|
|
8833
|
+
params.trackingOrderId,
|
|
8834
|
+
() => params.phase() === "tracking" && !!params.trackingOrderId()
|
|
8835
|
+
);
|
|
8836
|
+
createEffect(
|
|
8837
|
+
on(
|
|
8838
|
+
() => orderQuery.data,
|
|
8839
|
+
(order) => {
|
|
8840
|
+
if (!order || params.execPhase() !== "tracking") return;
|
|
8841
|
+
const isFilled = order.status === "filled" || order.stepsCompleted?.includes("filled");
|
|
8842
|
+
const isFailed = order.status === "failed" || order.status === "refunded";
|
|
8843
|
+
batch(() => {
|
|
8844
|
+
params.setOrder(order);
|
|
8845
|
+
if (isFilled) {
|
|
8846
|
+
params.setExecPhase("success");
|
|
8847
|
+
queryClient.invalidateQueries({
|
|
8848
|
+
queryKey: ["tokenBalances", params.client().baseUrl]
|
|
8849
|
+
});
|
|
8850
|
+
params.onOrderFilled(order);
|
|
8851
|
+
} else if (isFailed) {
|
|
8852
|
+
queryClient.invalidateQueries({
|
|
8853
|
+
queryKey: ["tokenBalances", params.client().baseUrl]
|
|
8854
|
+
});
|
|
8855
|
+
params.onOrderFailed(order);
|
|
8856
|
+
}
|
|
8857
|
+
});
|
|
8858
|
+
}
|
|
8859
|
+
)
|
|
8860
|
+
);
|
|
8861
|
+
return { orderQuery };
|
|
8862
|
+
}
|
|
8863
|
+
function useSwapExecution(params) {
|
|
8864
|
+
const [trackingOrderId, setTrackingOrderId] = createSignal(
|
|
8865
|
+
null
|
|
8866
|
+
);
|
|
8867
|
+
const [trackingProviderName, setTrackingProviderName] = createSignal(null);
|
|
8868
|
+
const [trackingProviderIcon, setTrackingProviderIcon] = createSignal(null);
|
|
8869
|
+
const [executionError, setExecutionError] = createSignal(null);
|
|
8870
|
+
const handleConfirm = async () => {
|
|
8871
|
+
const currentRoutes = params.routes();
|
|
8872
|
+
const currentQuoteId = params.quoteId();
|
|
8873
|
+
const selectedRoute = currentRoutes.find((r) => r.routeId === params.selectedRouteId()) ?? currentRoutes[0];
|
|
8874
|
+
if (!selectedRoute || !currentQuoteId || !params.client() || !params.walletAdapter())
|
|
8875
|
+
return;
|
|
8876
|
+
if (params.needRecipient() && !params.recipient()) {
|
|
8877
|
+
params.setError("Recipient address is required for cross-chain swaps");
|
|
8878
|
+
params.setErrorCode(ErrorCode.INVALID_CONFIG);
|
|
8879
|
+
return;
|
|
8880
|
+
}
|
|
8881
|
+
const fromChainType = getChainType(params.fromToken().chainId);
|
|
8882
|
+
const addr = params.walletAddress();
|
|
8883
|
+
if (!addr) {
|
|
8884
|
+
params.setError("Wallet not connected");
|
|
8885
|
+
params.setErrorCode(ErrorCode.WALLET_CONNECTION_FAILED);
|
|
8886
|
+
return;
|
|
8887
|
+
}
|
|
8888
|
+
if (!isAddressForChainType(addr, fromChainType)) {
|
|
8889
|
+
params.setError(t("error.walletChainMismatch"));
|
|
8890
|
+
params.setErrorCode(ErrorCode.INVALID_CONFIG);
|
|
8891
|
+
return;
|
|
8892
|
+
}
|
|
8893
|
+
setTrackingProviderName(selectedRoute.routeId ?? null);
|
|
8894
|
+
const apiBase = params.apiEndpoint() ?? DEFAULT_API_ENDPOINT;
|
|
8895
|
+
setTrackingProviderIcon(
|
|
8896
|
+
selectedRoute.icon ? `${apiBase}${selectedRoute.icon}` : null
|
|
8897
|
+
);
|
|
8898
|
+
setExecutionError(null);
|
|
8899
|
+
params.setExecPhase("building");
|
|
8900
|
+
try {
|
|
8901
|
+
const depositData = await params.client().buildDeposit({
|
|
8902
|
+
from: addr,
|
|
8903
|
+
quoteId: currentQuoteId,
|
|
8904
|
+
routeId: selectedRoute.routeId
|
|
8905
|
+
});
|
|
8906
|
+
params.setExecPhase("awaiting-wallet");
|
|
8907
|
+
let txHash;
|
|
8908
|
+
let signedTransaction;
|
|
8909
|
+
if (depositData.kind === "CONTRACT_CALL" && depositData.approvals) {
|
|
8910
|
+
for (const approval of depositData.approvals) {
|
|
8911
|
+
if (approval.type === "eip1193_request") {
|
|
8912
|
+
const result = await params.walletAdapter().executeWalletAction({
|
|
8913
|
+
type: "eip1193_request",
|
|
8914
|
+
chainId: params.fromToken().chainId,
|
|
8915
|
+
method: approval.request.method,
|
|
8916
|
+
params: approval.request.params
|
|
8917
|
+
});
|
|
8918
|
+
if (!result.success) {
|
|
8919
|
+
throw new TokenFlightError(
|
|
8920
|
+
ErrorCode.WALLET_ACTION_FAILED,
|
|
8921
|
+
result.error ?? "Wallet action failed"
|
|
8922
|
+
);
|
|
8923
|
+
}
|
|
8924
|
+
if (approval.deposit) {
|
|
8925
|
+
txHash = result.txHash ?? txHash;
|
|
8926
|
+
}
|
|
8927
|
+
} else if (approval.type === "solana_sendTransaction") {
|
|
8928
|
+
const result = await params.walletAdapter().executeWalletAction({
|
|
8929
|
+
type: "solana_signTransaction",
|
|
8930
|
+
transaction: approval.transaction
|
|
8931
|
+
});
|
|
8932
|
+
if (!result.success) {
|
|
8933
|
+
throw new TokenFlightError(
|
|
8934
|
+
ErrorCode.WALLET_ACTION_FAILED,
|
|
8935
|
+
result.error ?? "Wallet action failed"
|
|
8936
|
+
);
|
|
8937
|
+
}
|
|
8938
|
+
if (approval.deposit) {
|
|
8939
|
+
signedTransaction = typeof result.data === "string" ? result.data : void 0;
|
|
8940
|
+
}
|
|
8941
|
+
}
|
|
8942
|
+
}
|
|
8943
|
+
}
|
|
8944
|
+
if (!txHash && !signedTransaction) {
|
|
8945
|
+
throw new TokenFlightError(
|
|
8946
|
+
ErrorCode.TRANSACTION_FAILED,
|
|
8947
|
+
"No deposit transaction received"
|
|
8948
|
+
);
|
|
8949
|
+
}
|
|
8950
|
+
params.setExecPhase("submitting");
|
|
8951
|
+
const submitResult = await params.client().submitDeposit(
|
|
8952
|
+
signedTransaction ? {
|
|
8953
|
+
quoteId: currentQuoteId,
|
|
8954
|
+
routeId: selectedRoute.routeId,
|
|
8955
|
+
signedTransaction
|
|
8956
|
+
} : {
|
|
8957
|
+
quoteId: currentQuoteId,
|
|
8958
|
+
routeId: selectedRoute.routeId,
|
|
8959
|
+
txHash
|
|
8960
|
+
}
|
|
8961
|
+
);
|
|
8962
|
+
params.setExecPhase("tracking");
|
|
8963
|
+
setTrackingOrderId(submitResult.orderId);
|
|
8964
|
+
} catch (err) {
|
|
8965
|
+
const errorMsg = err instanceof Error ? err.message : typeof err === "string" ? err : "Transaction failed";
|
|
8966
|
+
setExecutionError(errorMsg);
|
|
8967
|
+
if (err instanceof TokenFlightError) {
|
|
8968
|
+
params.callbacks()?.onSwapError?.({
|
|
8969
|
+
code: err.code,
|
|
8970
|
+
message: err.message,
|
|
8971
|
+
details: err.details
|
|
8972
|
+
});
|
|
8973
|
+
} else {
|
|
8974
|
+
params.callbacks()?.onSwapError?.({
|
|
8975
|
+
code: ErrorCode.TRANSACTION_FAILED,
|
|
8976
|
+
message: String(err)
|
|
8977
|
+
});
|
|
8978
|
+
}
|
|
8979
|
+
}
|
|
8980
|
+
};
|
|
8981
|
+
const handleRetry = () => {
|
|
8982
|
+
setExecutionError(null);
|
|
8983
|
+
params.setExecPhase(null);
|
|
8984
|
+
};
|
|
8985
|
+
const handleNewSwap = () => {
|
|
8986
|
+
params.storeReset();
|
|
8987
|
+
setTrackingOrderId(null);
|
|
8988
|
+
setTrackingProviderName(null);
|
|
8989
|
+
setTrackingProviderIcon(null);
|
|
8990
|
+
setExecutionError(null);
|
|
8991
|
+
queryClient.removeQueries({ queryKey: ["quote", params.client().baseUrl] });
|
|
8992
|
+
queryClient.removeQueries({ queryKey: ["order", params.client().baseUrl] });
|
|
8993
|
+
params.onReset?.();
|
|
8994
|
+
};
|
|
8995
|
+
return {
|
|
8996
|
+
trackingOrderId,
|
|
8997
|
+
trackingProviderName,
|
|
8998
|
+
trackingProviderIcon,
|
|
8999
|
+
executionError,
|
|
9000
|
+
handleConfirm,
|
|
9001
|
+
handleRetry,
|
|
9002
|
+
handleNewSwap
|
|
9003
|
+
};
|
|
9004
|
+
}
|
|
8823
9005
|
const header$1 = "tf-dc5721";
|
|
8824
9006
|
const headerLeft = "tf-68123c";
|
|
8825
9007
|
const headerLogoImage = "tf-532d07";
|
|
@@ -8882,23 +9064,23 @@ const swapStyles = {
|
|
|
8882
9064
|
};
|
|
8883
9065
|
var _tmpl$$3 = /* @__PURE__ */ template(`<div data-testid=selector-overlay>`), _tmpl$2$2 = /* @__PURE__ */ template(`<div>`), _tmpl$3$2 = /* @__PURE__ */ template(`<div part=container><div part=accent-line data-testid=accent-line>`), _tmpl$4$2 = /* @__PURE__ */ template(`<img width=22 height=22>`), _tmpl$5$2 = /* @__PURE__ */ template(`<button part=wallet-info><div data-testid=wallet-dot></div><span data-testid=wallet-address>`), _tmpl$6$2 = /* @__PURE__ */ template(`<div part=header><div><span data-testid=header-title>`), _tmpl$7$2 = /* @__PURE__ */ template(`<div><span part=balance data-testid=panel-balance></span><button data-testid=max-btn>`), _tmpl$8$2 = /* @__PURE__ */ template(`<button part=token-display data-testid=token-btn><div data-testid=token-icon-wrap><div data-testid=token-chain-dot></div></div><span data-testid=token-name></span><span data-testid=caret>`), _tmpl$9$2 = /* @__PURE__ */ template(`<div part=panel-from><div><div><span data-testid=panel-label></span></div><div></div><div><span data-testid=fiat>`), _tmpl$0$2 = /* @__PURE__ */ template(`<div part=swap-arrow><button type=button data-testid=swap-arrow-inner>`), _tmpl$1$2 = /* @__PURE__ */ template(`<button part=recipient-badge data-testid=recipient-badge><span>`), _tmpl$10$2 = /* @__PURE__ */ template(`<span part=amount-display data-testid=amount style=cursor:default>`), _tmpl$11$1 = /* @__PURE__ */ template(`<div part=panel-to data-testid=panel-wrapper-to><div><div><span data-testid=panel-label></span></div><div></div><div><span data-testid=fiat>`), _tmpl$12$1 = /* @__PURE__ */ template(`<div part=price-preview data-testid=quote>`), _tmpl$13 = /* @__PURE__ */ template(`<div part=no-offer><div><svg width=28 height=28 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><circle cx=11 cy=11 r=8></circle><path d="m21 21-4.35-4.35"></path><path d="M8 11h6"></path></svg></div><span>`), _tmpl$14 = /* @__PURE__ */ template(`<div part=cta-wrapper>`), _tmpl$15 = /* @__PURE__ */ template(`<span>Flight`), _tmpl$16 = /* @__PURE__ */ template(`<button data-testid=token-btn><span data-testid=token-name></span><span data-testid=caret>`), _tmpl$17 = /* @__PURE__ */ template(`<div style=width:120px;height:28px>`);
|
|
8884
9066
|
function SwapComponent(props) {
|
|
8885
|
-
const
|
|
9067
|
+
const store = createSwapStore();
|
|
8886
9068
|
const [selectorOpen, setSelectorOpen] = createSignal(null);
|
|
8887
|
-
const [isConnected, setIsConnected] = createSignal(false);
|
|
8888
|
-
const [walletAddress2, setWalletAddress] = createSignal(null);
|
|
8889
|
-
const [trackingOrderId, setTrackingOrderId] = createSignal(null);
|
|
8890
9069
|
const [recipientEditorOpen, setRecipientEditorOpen] = createSignal(false);
|
|
8891
|
-
const
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
9070
|
+
const {
|
|
9071
|
+
isConnected,
|
|
9072
|
+
walletAddress: walletAddress2,
|
|
9073
|
+
handleConnect
|
|
9074
|
+
} = useWalletConnection({
|
|
9075
|
+
walletAdapter: () => props.walletAdapter,
|
|
9076
|
+
callbacks: () => props.callbacks,
|
|
9077
|
+
onAddressChange: (addr) => store.setWalletAddress(addr),
|
|
9078
|
+
onConnectError: (msg, code) => {
|
|
9079
|
+
store.setError(msg);
|
|
9080
|
+
store.setErrorCode(code);
|
|
9081
|
+
}
|
|
9082
|
+
});
|
|
8895
9083
|
const [debouncedAmount, setDebouncedAmount, setDebouncedAmountImmediate] = createDebounced("", 300);
|
|
8896
|
-
const phase = createMemo(() => sm.state().phase);
|
|
8897
|
-
const fromToken = createMemo(() => sm.state().fromToken);
|
|
8898
|
-
const toToken = createMemo(() => sm.state().toToken);
|
|
8899
|
-
const inputAmount = createMemo(() => sm.state().inputAmount);
|
|
8900
|
-
const outputAmount = createMemo(() => sm.state().outputAmount);
|
|
8901
|
-
const recipient = createMemo(() => sm.state().recipient);
|
|
8902
9084
|
const client = createMemo(() => {
|
|
8903
9085
|
const endpoint = props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
|
|
8904
9086
|
return new HyperstreamApi({
|
|
@@ -8907,7 +9089,7 @@ function SwapComponent(props) {
|
|
|
8907
9089
|
});
|
|
8908
9090
|
const balancesQuery = createTokenBalancesQuery(client, walletAddress2, () => isConnected() && !!walletAddress2(), () => props.walletAdapter?.supportedChainIds);
|
|
8909
9091
|
const fromBalance = createMemo(() => {
|
|
8910
|
-
const from = fromToken();
|
|
9092
|
+
const from = store.fromToken();
|
|
8911
9093
|
if (!from || typeof from.decimals !== "number" || !balancesQuery.data) return null;
|
|
8912
9094
|
const match = balancesQuery.data.find((tk) => tk.address.toLowerCase() === from.address.toLowerCase() && tk.chainId === from.chainId);
|
|
8913
9095
|
if (match?.extensions?.balance) {
|
|
@@ -8916,14 +9098,14 @@ function SwapComponent(props) {
|
|
|
8916
9098
|
return "0";
|
|
8917
9099
|
});
|
|
8918
9100
|
const fromBalanceRaw = createMemo(() => {
|
|
8919
|
-
const from = fromToken();
|
|
9101
|
+
const from = store.fromToken();
|
|
8920
9102
|
if (!from || typeof from.decimals !== "number" || !balancesQuery.data) return null;
|
|
8921
9103
|
const match = balancesQuery.data.find((tk) => tk.address.toLowerCase() === from.address.toLowerCase() && tk.chainId === from.chainId);
|
|
8922
9104
|
return match?.extensions?.balance ?? "0";
|
|
8923
9105
|
});
|
|
8924
9106
|
const insufficientBalance = createMemo(() => {
|
|
8925
|
-
const input = inputAmount();
|
|
8926
|
-
const from = fromToken();
|
|
9107
|
+
const input = store.inputAmount();
|
|
9108
|
+
const from = store.fromToken();
|
|
8927
9109
|
const balRaw = fromBalanceRaw();
|
|
8928
9110
|
if (!from || typeof from.decimals !== "number" || !balRaw || !input || input === "0" || input === "") {
|
|
8929
9111
|
return false;
|
|
@@ -8935,7 +9117,7 @@ function SwapComponent(props) {
|
|
|
8935
9117
|
}
|
|
8936
9118
|
});
|
|
8937
9119
|
const fromUnitPriceUsd = createMemo(() => {
|
|
8938
|
-
const from = fromToken();
|
|
9120
|
+
const from = store.fromToken();
|
|
8939
9121
|
if (!from) return null;
|
|
8940
9122
|
if (typeof from.priceUsd === "number" && Number.isFinite(from.priceUsd)) {
|
|
8941
9123
|
return from.priceUsd;
|
|
@@ -8945,7 +9127,7 @@ function SwapComponent(props) {
|
|
|
8945
9127
|
return Number.isFinite(parsed) ? parsed : null;
|
|
8946
9128
|
});
|
|
8947
9129
|
const toUnitPriceUsd = createMemo(() => {
|
|
8948
|
-
const to = toToken();
|
|
9130
|
+
const to = store.toToken();
|
|
8949
9131
|
if (!to) return null;
|
|
8950
9132
|
if (typeof to.priceUsd === "number" && Number.isFinite(to.priceUsd)) {
|
|
8951
9133
|
return to.priceUsd;
|
|
@@ -8957,178 +9139,24 @@ function SwapComponent(props) {
|
|
|
8957
9139
|
if (value2 < 0.01) return "<0.01";
|
|
8958
9140
|
return value2.toFixed(2).replace(/\.?0+$/, "");
|
|
8959
9141
|
};
|
|
8960
|
-
const
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
const show = p === "quoted" || p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking" || p === "success";
|
|
8973
|
-
if (!show || !Number.isFinite(amount2) || amount2 <= 0 || price === null) return null;
|
|
8974
|
-
return t("swap.fiatValue", {
|
|
8975
|
-
value: formatUsd(amount2 * price)
|
|
8976
|
-
});
|
|
8977
|
-
});
|
|
8978
|
-
const orderQuery = createOrderQuery(client, walletAddress2, trackingOrderId, () => phase() === "tracking" && !!trackingOrderId());
|
|
8979
|
-
createEffect(on(() => orderQuery.data, (order) => {
|
|
8980
|
-
if (!order || sm.state().phase !== "tracking") return;
|
|
8981
|
-
const isFilled = order.status === "filled" || order.stepsCompleted?.includes("filled");
|
|
8982
|
-
const isFailed = order.status === "failed" || order.status === "refunded";
|
|
8983
|
-
batch(() => {
|
|
8984
|
-
sm.setOrder(order);
|
|
8985
|
-
if (isFilled) {
|
|
8986
|
-
sm.transition("success");
|
|
8987
|
-
queryClient.invalidateQueries({
|
|
8988
|
-
queryKey: ["tokenBalances", client().baseUrl]
|
|
8989
|
-
});
|
|
8990
|
-
const state2 = sm.state();
|
|
8991
|
-
props.callbacks?.onSwapSuccess?.({
|
|
8992
|
-
orderId: order.id,
|
|
8993
|
-
fromToken: state2.fromToken.symbol ?? state2.fromToken.address,
|
|
8994
|
-
toToken: state2.toToken.symbol ?? state2.toToken.address,
|
|
8995
|
-
fromAmount: order.srcAmount,
|
|
8996
|
-
toAmount: order.destAmount,
|
|
8997
|
-
txHash: order.depositTxHash
|
|
8998
|
-
});
|
|
8999
|
-
} else if (isFailed) {
|
|
9000
|
-
queryClient.invalidateQueries({
|
|
9001
|
-
queryKey: ["tokenBalances", client().baseUrl]
|
|
9002
|
-
});
|
|
9003
|
-
props.callbacks?.onSwapError?.({
|
|
9004
|
-
code: ErrorCode.ORDER_FAILED,
|
|
9005
|
-
message: "Order " + order.status
|
|
9006
|
-
});
|
|
9007
|
-
}
|
|
9008
|
-
});
|
|
9009
|
-
}));
|
|
9010
|
-
onMount(() => {
|
|
9011
|
-
if (props.config.locale) {
|
|
9012
|
-
setLocale(props.config.locale);
|
|
9013
|
-
}
|
|
9014
|
-
});
|
|
9015
|
-
const chainsQuery = createChainsQuery(client, () => true);
|
|
9016
|
-
const chainMap = createMemo(() => {
|
|
9017
|
-
const data = chainsQuery.data;
|
|
9018
|
-
return data ? buildChainMap(data) : /* @__PURE__ */ new Map();
|
|
9019
|
-
});
|
|
9020
|
-
onMount(async () => {
|
|
9021
|
-
const c = client();
|
|
9022
|
-
if (props.config.fromToken) {
|
|
9023
|
-
try {
|
|
9024
|
-
const target2 = parseTokenIdentifier(props.config.fromToken);
|
|
9025
|
-
const resolved = await resolveToken(target2.chainId, target2.address, props.config.apiEndpoint, c);
|
|
9026
|
-
if (typeof resolved.decimals !== "number") {
|
|
9027
|
-
throw new TokenFlightError(ErrorCode.INVALID_TOKEN_IDENTIFIER, "Failed to resolve fromToken metadata");
|
|
9028
|
-
}
|
|
9029
|
-
sm.setFromToken(resolved);
|
|
9030
|
-
} catch (err) {
|
|
9031
|
-
props.callbacks?.onSwapError?.({
|
|
9032
|
-
code: ErrorCode.INVALID_TOKEN_IDENTIFIER,
|
|
9033
|
-
message: `Failed to resolve fromToken: ${err instanceof Error ? err.message : String(err)}`
|
|
9034
|
-
});
|
|
9035
|
-
}
|
|
9036
|
-
}
|
|
9037
|
-
if (props.config.toToken) {
|
|
9038
|
-
try {
|
|
9039
|
-
const target2 = parseTokenIdentifier(props.config.toToken);
|
|
9040
|
-
const resolved = await resolveToken(target2.chainId, target2.address, props.config.apiEndpoint, c);
|
|
9041
|
-
if (typeof resolved.decimals !== "number") {
|
|
9042
|
-
throw new TokenFlightError(ErrorCode.INVALID_TOKEN_IDENTIFIER, "Failed to resolve toToken metadata");
|
|
9043
|
-
}
|
|
9044
|
-
sm.setToToken(resolved);
|
|
9045
|
-
} catch (err) {
|
|
9046
|
-
props.callbacks?.onSwapError?.({
|
|
9047
|
-
code: ErrorCode.INVALID_TOKEN_IDENTIFIER,
|
|
9048
|
-
message: `Failed to resolve toToken: ${err instanceof Error ? err.message : String(err)}`
|
|
9049
|
-
});
|
|
9050
|
-
}
|
|
9051
|
-
}
|
|
9052
|
-
});
|
|
9053
|
-
const detectChainType = () => {
|
|
9054
|
-
if (!props.walletAdapter) return "evm";
|
|
9055
|
-
return props.walletAdapter.supportedActionTypes.some((t2) => t2.startsWith("solana_")) ? "solana" : "evm";
|
|
9056
|
-
};
|
|
9057
|
-
const needRecipient = createMemo(() => {
|
|
9058
|
-
const from = fromToken();
|
|
9059
|
-
const to = toToken();
|
|
9060
|
-
if (!from || !to || !isConnected()) return false;
|
|
9061
|
-
return isCrossChainSwap(from.chainId, to.chainId);
|
|
9062
|
-
});
|
|
9063
|
-
const recipientDisplay = createMemo(() => {
|
|
9064
|
-
const r = recipient();
|
|
9065
|
-
if (r) return r;
|
|
9066
|
-
if (isConnected() && walletAddress2() && !needRecipient()) return walletAddress2();
|
|
9067
|
-
return null;
|
|
9068
|
-
});
|
|
9069
|
-
onMount(() => {
|
|
9070
|
-
if (props.config.recipient) {
|
|
9071
|
-
sm.setRecipient(props.config.recipient);
|
|
9072
|
-
}
|
|
9073
|
-
});
|
|
9074
|
-
const handleRecipientChange = (value2) => {
|
|
9075
|
-
const trimmed = value2.trim() || null;
|
|
9076
|
-
sm.setRecipient(trimmed);
|
|
9077
|
-
if (!trimmed) {
|
|
9078
|
-
sm.clearRoutes();
|
|
9079
|
-
sm.setOutputAmount("");
|
|
9080
|
-
if (sm.state().phase !== "idle") {
|
|
9081
|
-
sm.transition("idle");
|
|
9082
|
-
}
|
|
9083
|
-
}
|
|
9084
|
-
};
|
|
9085
|
-
onMount(async () => {
|
|
9086
|
-
if (props.walletAdapter) {
|
|
9087
|
-
const connected = props.walletAdapter.isConnected();
|
|
9088
|
-
setIsConnected(connected);
|
|
9089
|
-
if (connected) {
|
|
9090
|
-
const addr = await props.walletAdapter.getAddress();
|
|
9091
|
-
setWalletAddress(addr);
|
|
9092
|
-
sm.setWalletAddress(addr);
|
|
9093
|
-
props.callbacks?.onWalletConnected?.({
|
|
9094
|
-
address: addr ?? "",
|
|
9095
|
-
chainType: detectChainType()
|
|
9096
|
-
});
|
|
9097
|
-
}
|
|
9098
|
-
const handleWalletConnect = async () => {
|
|
9099
|
-
const addr = await props.walletAdapter.getAddress();
|
|
9100
|
-
if (isConnected() && walletAddress2() === addr) return;
|
|
9101
|
-
batch(() => {
|
|
9102
|
-
setIsConnected(true);
|
|
9103
|
-
setWalletAddress(addr);
|
|
9104
|
-
sm.setWalletAddress(addr);
|
|
9105
|
-
});
|
|
9106
|
-
props.callbacks?.onWalletConnected?.({
|
|
9107
|
-
address: addr ?? "",
|
|
9108
|
-
chainType: detectChainType()
|
|
9109
|
-
});
|
|
9110
|
-
};
|
|
9111
|
-
const handleWalletDisconnect = () => {
|
|
9112
|
-
if (!isConnected()) return;
|
|
9113
|
-
batch(() => {
|
|
9114
|
-
setIsConnected(false);
|
|
9115
|
-
setWalletAddress(null);
|
|
9116
|
-
sm.setWalletAddress(null);
|
|
9117
|
-
});
|
|
9118
|
-
};
|
|
9119
|
-
props.walletAdapter.on("connect", handleWalletConnect);
|
|
9120
|
-
props.walletAdapter.on("disconnect", handleWalletDisconnect);
|
|
9121
|
-
onCleanup(() => {
|
|
9122
|
-
props.walletAdapter.off("connect", handleWalletConnect);
|
|
9123
|
-
props.walletAdapter.off("disconnect", handleWalletDisconnect);
|
|
9124
|
-
});
|
|
9125
|
-
}
|
|
9142
|
+
const {
|
|
9143
|
+
needRecipient,
|
|
9144
|
+
recipientDisplay,
|
|
9145
|
+
handleRecipientChange
|
|
9146
|
+
} = useRecipient({
|
|
9147
|
+
fromToken: store.fromToken,
|
|
9148
|
+
toToken: store.toToken,
|
|
9149
|
+
recipient: store.recipient,
|
|
9150
|
+
isConnected,
|
|
9151
|
+
walletAddress: walletAddress2,
|
|
9152
|
+
walletAdapter: () => props.walletAdapter,
|
|
9153
|
+
setRecipient: store.setRecipient
|
|
9126
9154
|
});
|
|
9127
9155
|
const quoteRequest = createMemo(() => {
|
|
9128
9156
|
const amount2 = debouncedAmount();
|
|
9129
|
-
const from = fromToken();
|
|
9130
|
-
const to = toToken();
|
|
9131
|
-
const r = recipient();
|
|
9157
|
+
const from = store.fromToken();
|
|
9158
|
+
const to = store.toToken();
|
|
9159
|
+
const r = store.recipient();
|
|
9132
9160
|
if (!amount2 || parseFloat(amount2) <= 0 || !from || typeof from.decimals !== "number" || !to || !client()) return null;
|
|
9133
9161
|
if (needRecipient() && !r) return null;
|
|
9134
9162
|
return {
|
|
@@ -9144,238 +9172,204 @@ function SwapComponent(props) {
|
|
|
9144
9172
|
}
|
|
9145
9173
|
};
|
|
9146
9174
|
});
|
|
9147
|
-
const quoteQueryEnabled = createMemo(() =>
|
|
9175
|
+
const quoteQueryEnabled = createMemo(() => !!quoteRequest() && !store.execPhase());
|
|
9176
|
+
const quoteQuery = createQuoteQuery(client, quoteRequest, quoteQueryEnabled);
|
|
9177
|
+
const routes = createMemo(() => {
|
|
9178
|
+
const amount2 = store.inputAmount();
|
|
9179
|
+
if (!amount2 || parseFloat(amount2) <= 0) return [];
|
|
9180
|
+
if (!store.fromToken() || !store.toToken()) return [];
|
|
9181
|
+
return quoteQuery.data?.routes ?? [];
|
|
9182
|
+
});
|
|
9183
|
+
const quoteId = createMemo(() => quoteQuery.data?.quoteId ?? null);
|
|
9184
|
+
const selectedRouteId = createMemo(() => {
|
|
9185
|
+
const r = routes();
|
|
9186
|
+
return r.length > 0 ? getBestOverallSwapRouteId(r) : null;
|
|
9187
|
+
});
|
|
9188
|
+
const bestRoute = createMemo(() => {
|
|
9189
|
+
const r = routes();
|
|
9190
|
+
const sel = selectedRouteId();
|
|
9191
|
+
return r.find((rt) => rt.routeId === sel) ?? r[0] ?? null;
|
|
9192
|
+
});
|
|
9193
|
+
const outputAmount = createMemo(() => {
|
|
9194
|
+
const route = bestRoute();
|
|
9195
|
+
const to = store.toToken();
|
|
9196
|
+
if (!route || !to || typeof to.decimals !== "number") return "";
|
|
9197
|
+
return formatDisplayAmount(toDisplayAmount(route.quote.amountOut, to.decimals));
|
|
9198
|
+
});
|
|
9199
|
+
const phase = createMemo(() => deriveSwapPhase(store.execPhase(), store.error(), quoteQuery.isFetching, routes().length, !!quoteRequest()));
|
|
9200
|
+
const noRoutes = createMemo(() => {
|
|
9201
|
+
if (store.execPhase()) return false;
|
|
9202
|
+
if (!quoteRequest()) return false;
|
|
9203
|
+
return !quoteQuery.isFetching && quoteQuery.isSuccess && routes().length === 0;
|
|
9204
|
+
});
|
|
9205
|
+
const showQuote = createMemo(() => {
|
|
9206
|
+
const p = phase();
|
|
9207
|
+
return p === "quoted" || p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking" || p === "success";
|
|
9208
|
+
});
|
|
9209
|
+
const isExecuting = createMemo(() => {
|
|
9148
9210
|
const p = phase();
|
|
9149
|
-
|
|
9150
|
-
|
|
9211
|
+
return p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking";
|
|
9212
|
+
});
|
|
9213
|
+
const isQuoteLoading = createMemo(() => {
|
|
9214
|
+
if (!store.fromToken() || !store.toToken()) return false;
|
|
9215
|
+
return phase() === "quoting" && parseFloat(store.inputAmount()) > 0 && routes().length === 0;
|
|
9216
|
+
});
|
|
9217
|
+
const inputFiatText = createMemo(() => {
|
|
9218
|
+
const amount2 = Number(store.inputAmount());
|
|
9219
|
+
const price = fromUnitPriceUsd();
|
|
9220
|
+
if (!Number.isFinite(amount2) || amount2 <= 0 || price === null) return null;
|
|
9221
|
+
return t("swap.fiatValue", {
|
|
9222
|
+
value: formatUsd(amount2 * price)
|
|
9223
|
+
});
|
|
9224
|
+
});
|
|
9225
|
+
const outputFiatText = createMemo(() => {
|
|
9226
|
+
const amount2 = Number(outputAmount() || "0");
|
|
9227
|
+
const price = toUnitPriceUsd();
|
|
9228
|
+
if (!showQuote() || !Number.isFinite(amount2) || amount2 <= 0 || price === null) return null;
|
|
9229
|
+
return t("swap.fiatValue", {
|
|
9230
|
+
value: formatUsd(amount2 * price)
|
|
9231
|
+
});
|
|
9232
|
+
});
|
|
9233
|
+
const {
|
|
9234
|
+
trackingOrderId,
|
|
9235
|
+
trackingProviderName,
|
|
9236
|
+
trackingProviderIcon,
|
|
9237
|
+
executionError,
|
|
9238
|
+
handleConfirm,
|
|
9239
|
+
handleRetry,
|
|
9240
|
+
handleNewSwap
|
|
9241
|
+
} = useSwapExecution({
|
|
9242
|
+
client,
|
|
9243
|
+
walletAdapter: () => props.walletAdapter,
|
|
9244
|
+
callbacks: () => props.callbacks,
|
|
9245
|
+
apiEndpoint: () => props.config.apiEndpoint,
|
|
9246
|
+
fromToken: store.fromToken,
|
|
9247
|
+
recipient: store.recipient,
|
|
9248
|
+
needRecipient,
|
|
9249
|
+
walletAddress: walletAddress2,
|
|
9250
|
+
routes,
|
|
9251
|
+
quoteId,
|
|
9252
|
+
selectedRouteId,
|
|
9253
|
+
setExecPhase: store.setExecPhase,
|
|
9254
|
+
setError: store.setError,
|
|
9255
|
+
setErrorCode: store.setErrorCode,
|
|
9256
|
+
storeReset: store.reset,
|
|
9257
|
+
onReset: () => setDebouncedAmountImmediate("")
|
|
9258
|
+
});
|
|
9259
|
+
useOrderTracking({
|
|
9260
|
+
client,
|
|
9261
|
+
walletAddress: walletAddress2,
|
|
9262
|
+
trackingOrderId,
|
|
9263
|
+
phase,
|
|
9264
|
+
execPhase: store.execPhase,
|
|
9265
|
+
setOrder: store.setOrder,
|
|
9266
|
+
setExecPhase: store.setExecPhase,
|
|
9267
|
+
onOrderFilled: (order) => {
|
|
9268
|
+
props.callbacks?.onSwapSuccess?.({
|
|
9269
|
+
orderId: order.id,
|
|
9270
|
+
fromToken: store.fromToken().symbol ?? store.fromToken().address,
|
|
9271
|
+
toToken: store.toToken().symbol ?? store.toToken().address,
|
|
9272
|
+
fromAmount: order.srcAmount,
|
|
9273
|
+
toAmount: order.destAmount,
|
|
9274
|
+
txHash: order.depositTxHash
|
|
9275
|
+
});
|
|
9276
|
+
},
|
|
9277
|
+
onOrderFailed: (order) => {
|
|
9278
|
+
props.callbacks?.onSwapError?.({
|
|
9279
|
+
code: ErrorCode.ORDER_FAILED,
|
|
9280
|
+
message: "Order " + order.status
|
|
9281
|
+
});
|
|
9282
|
+
}
|
|
9151
9283
|
});
|
|
9152
|
-
const quoteQuery = createQuoteQuery(client, quoteRequest, quoteQueryEnabled);
|
|
9153
9284
|
createEffect(on(() => quoteQuery.data, (data) => {
|
|
9154
9285
|
if (data) props.callbacks?.onQuoteReceived?.(data);
|
|
9155
9286
|
}));
|
|
9156
9287
|
createEffect(on(() => ({
|
|
9157
|
-
data: quoteQuery.data,
|
|
9158
|
-
isFetching: quoteQuery.isFetching,
|
|
9159
9288
|
isError: quoteQuery.isError,
|
|
9160
|
-
error: quoteQuery.error
|
|
9289
|
+
error: quoteQuery.error,
|
|
9290
|
+
data: quoteQuery.data
|
|
9161
9291
|
}), ({
|
|
9162
|
-
data,
|
|
9163
|
-
isFetching,
|
|
9164
9292
|
isError,
|
|
9165
|
-
error: error2
|
|
9293
|
+
error: error2,
|
|
9294
|
+
data
|
|
9166
9295
|
}) => {
|
|
9167
|
-
|
|
9168
|
-
if (phase2 === "building" || phase2 === "awaiting-wallet" || phase2 === "submitting" || phase2 === "tracking" || phase2 === "success") return;
|
|
9169
|
-
if (isFetching && !data) {
|
|
9170
|
-
if (phase2 !== "quoting") {
|
|
9171
|
-
sm.clearRoutes();
|
|
9172
|
-
setNoRoutes(false);
|
|
9173
|
-
sm.transition("quoting");
|
|
9174
|
-
}
|
|
9175
|
-
return;
|
|
9176
|
-
}
|
|
9296
|
+
if (store.execPhase()) return;
|
|
9177
9297
|
if (isError && !data) {
|
|
9178
9298
|
if (error2 instanceof TokenFlightError) {
|
|
9179
|
-
|
|
9299
|
+
store.setError(error2.message);
|
|
9300
|
+
store.setErrorCode(error2.code);
|
|
9180
9301
|
} else {
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
return;
|
|
9184
|
-
}
|
|
9185
|
-
if (data) {
|
|
9186
|
-
const toDecimals = sm.state().toToken?.decimals ?? 18;
|
|
9187
|
-
const bestId = getBestOverallSwapRouteId(data.routes);
|
|
9188
|
-
sm.setQuoteData(data.quoteId, data.routes, bestId);
|
|
9189
|
-
if (bestId) {
|
|
9190
|
-
const bestRoute2 = data.routes.find((r) => r.routeId === bestId);
|
|
9191
|
-
if (bestRoute2) {
|
|
9192
|
-
sm.setOutputAmount(formatDisplayAmount(toDisplayAmount(bestRoute2.quote.amountOut, toDecimals)));
|
|
9193
|
-
}
|
|
9194
|
-
}
|
|
9195
|
-
if (data.routes.length > 0) {
|
|
9196
|
-
setNoRoutes(false);
|
|
9197
|
-
if (phase2 !== "quoted") sm.transition("quoted");
|
|
9198
|
-
} else {
|
|
9199
|
-
setNoRoutes(true);
|
|
9200
|
-
if (phase2 !== "idle") sm.transition("idle");
|
|
9201
|
-
}
|
|
9202
|
-
}
|
|
9203
|
-
}));
|
|
9204
|
-
const [countdownSeconds, setCountdownSeconds] = createSignal(QUOTE_REFRESH_SECONDS);
|
|
9205
|
-
createEffect(on(phase, (p) => {
|
|
9206
|
-
if (p !== "quoted") {
|
|
9207
|
-
setCountdownSeconds(QUOTE_REFRESH_SECONDS);
|
|
9208
|
-
return;
|
|
9209
|
-
}
|
|
9210
|
-
setCountdownSeconds(QUOTE_REFRESH_SECONDS);
|
|
9211
|
-
const timer = setInterval(() => {
|
|
9212
|
-
setCountdownSeconds((prev) => {
|
|
9213
|
-
if (prev <= 1) {
|
|
9214
|
-
quoteQuery.refetch();
|
|
9215
|
-
return QUOTE_REFRESH_SECONDS;
|
|
9216
|
-
}
|
|
9217
|
-
return prev - 1;
|
|
9218
|
-
});
|
|
9219
|
-
}, 1e3);
|
|
9220
|
-
onCleanup(() => clearInterval(timer));
|
|
9221
|
-
}));
|
|
9222
|
-
const handleAmountChange = (amount2) => {
|
|
9223
|
-
sm.setInputAmount(amount2);
|
|
9224
|
-
props.callbacks?.onAmountChanged?.({
|
|
9225
|
-
amount: amount2,
|
|
9226
|
-
direction: "from"
|
|
9227
|
-
});
|
|
9228
|
-
if (!amount2 || parseFloat(amount2) <= 0) {
|
|
9229
|
-
sm.clearRoutes();
|
|
9230
|
-
sm.setOutputAmount("");
|
|
9231
|
-
setNoRoutes(false);
|
|
9232
|
-
if (sm.state().phase !== "idle") {
|
|
9233
|
-
sm.transition("idle");
|
|
9302
|
+
store.setError(String(error2));
|
|
9303
|
+
store.setErrorCode(null);
|
|
9234
9304
|
}
|
|
9235
|
-
} else if (
|
|
9236
|
-
|
|
9237
|
-
}
|
|
9238
|
-
setDebouncedAmount(amount2);
|
|
9239
|
-
};
|
|
9240
|
-
createEffect(on(needRecipient, (need) => {
|
|
9241
|
-
if (need && !recipient() && props.walletAdapter) {
|
|
9242
|
-
const to = toToken();
|
|
9243
|
-
if (!to) return;
|
|
9244
|
-
const targetChainType = getChainType(to.chainId);
|
|
9245
|
-
props.walletAdapter.getAddress(targetChainType).then((addr) => {
|
|
9246
|
-
if (addr && isAddressForChainType(addr, targetChainType) && !recipient() && needRecipient()) {
|
|
9247
|
-
sm.setRecipient(addr);
|
|
9248
|
-
}
|
|
9249
|
-
}).catch(() => {
|
|
9250
|
-
});
|
|
9305
|
+
} else if (store.error() && !isError) {
|
|
9306
|
+
store.clearError();
|
|
9251
9307
|
}
|
|
9252
9308
|
}));
|
|
9253
|
-
const
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
try {
|
|
9260
|
-
await props.walletAdapter.connect();
|
|
9261
|
-
} catch {
|
|
9262
|
-
sm.setError("Failed to connect wallet", ErrorCode.WALLET_CONNECTION_FAILED);
|
|
9263
|
-
}
|
|
9264
|
-
};
|
|
9265
|
-
const handleConfirm = async () => {
|
|
9266
|
-
const state2 = sm.state();
|
|
9267
|
-
const selectedRoute = state2.routes.find((r) => r.routeId === state2.selectedRouteId) ?? state2.routes[0];
|
|
9268
|
-
if (!selectedRoute || !state2.quoteId || !client() || !props.walletAdapter) return;
|
|
9269
|
-
if (needRecipient() && !state2.recipient) {
|
|
9270
|
-
sm.setError("Recipient address is required for cross-chain swaps", ErrorCode.INVALID_CONFIG);
|
|
9271
|
-
return;
|
|
9272
|
-
}
|
|
9273
|
-
const fromChainType = getChainType(state2.fromToken.chainId);
|
|
9274
|
-
const addr = walletAddress2();
|
|
9275
|
-
if (!addr) {
|
|
9276
|
-
sm.setError("Wallet not connected", ErrorCode.WALLET_CONNECTION_FAILED);
|
|
9277
|
-
return;
|
|
9309
|
+
const {
|
|
9310
|
+
countdownSeconds
|
|
9311
|
+
} = useQuoteCountdown({
|
|
9312
|
+
phase,
|
|
9313
|
+
onExpired: () => {
|
|
9314
|
+
quoteQuery.refetch();
|
|
9278
9315
|
}
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9316
|
+
});
|
|
9317
|
+
onMount(() => {
|
|
9318
|
+
if (props.config.locale) {
|
|
9319
|
+
setLocale(props.config.locale);
|
|
9282
9320
|
}
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
if (depositData.kind === "CONTRACT_CALL" && depositData.approvals) {
|
|
9298
|
-
for (const approval of depositData.approvals) {
|
|
9299
|
-
if (approval.type === "eip1193_request") {
|
|
9300
|
-
const result = await props.walletAdapter.executeWalletAction({
|
|
9301
|
-
type: "eip1193_request",
|
|
9302
|
-
chainId: state2.fromToken.chainId,
|
|
9303
|
-
method: approval.request.method,
|
|
9304
|
-
params: approval.request.params
|
|
9305
|
-
});
|
|
9306
|
-
if (!result.success) {
|
|
9307
|
-
throw new TokenFlightError(ErrorCode.WALLET_ACTION_FAILED, result.error ?? "Wallet action failed");
|
|
9308
|
-
}
|
|
9309
|
-
if (approval.deposit) {
|
|
9310
|
-
txHash = result.txHash ?? txHash;
|
|
9311
|
-
}
|
|
9312
|
-
} else if (approval.type === "solana_sendTransaction") {
|
|
9313
|
-
const result = await props.walletAdapter.executeWalletAction({
|
|
9314
|
-
type: "solana_signTransaction",
|
|
9315
|
-
transaction: approval.transaction
|
|
9316
|
-
});
|
|
9317
|
-
if (!result.success) {
|
|
9318
|
-
throw new TokenFlightError(ErrorCode.WALLET_ACTION_FAILED, result.error ?? "Wallet action failed");
|
|
9319
|
-
}
|
|
9320
|
-
if (approval.deposit) {
|
|
9321
|
-
signedTransaction = typeof result.data === "string" ? result.data : void 0;
|
|
9322
|
-
}
|
|
9323
|
-
}
|
|
9321
|
+
});
|
|
9322
|
+
const chainsQuery = createChainsQuery(client, () => true);
|
|
9323
|
+
const chainMap = createMemo(() => {
|
|
9324
|
+
const data = chainsQuery.data;
|
|
9325
|
+
return data ? buildChainMap(data) : /* @__PURE__ */ new Map();
|
|
9326
|
+
});
|
|
9327
|
+
onMount(async () => {
|
|
9328
|
+
const c = client();
|
|
9329
|
+
if (props.config.fromToken) {
|
|
9330
|
+
try {
|
|
9331
|
+
const target2 = parseTokenIdentifier(props.config.fromToken);
|
|
9332
|
+
const resolved = await resolveToken(target2.chainId, target2.address, props.config.apiEndpoint, c);
|
|
9333
|
+
if (typeof resolved.decimals !== "number") {
|
|
9334
|
+
throw new TokenFlightError(ErrorCode.INVALID_TOKEN_IDENTIFIER, "Failed to resolve fromToken metadata");
|
|
9324
9335
|
}
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
throw new TokenFlightError(ErrorCode.TRANSACTION_FAILED, "No deposit transaction received");
|
|
9328
|
-
}
|
|
9329
|
-
sm.transition("submitting");
|
|
9330
|
-
const submitResult = await client().submitDeposit(signedTransaction ? {
|
|
9331
|
-
quoteId: state2.quoteId,
|
|
9332
|
-
routeId: selectedRoute.routeId,
|
|
9333
|
-
signedTransaction
|
|
9334
|
-
} : {
|
|
9335
|
-
quoteId: state2.quoteId,
|
|
9336
|
-
routeId: selectedRoute.routeId,
|
|
9337
|
-
txHash
|
|
9338
|
-
});
|
|
9339
|
-
sm.transition("tracking");
|
|
9340
|
-
setTrackingOrderId(submitResult.orderId);
|
|
9341
|
-
} catch (err) {
|
|
9342
|
-
const errorMsg = err instanceof Error ? err.message : typeof err === "string" ? err : "Transaction failed";
|
|
9343
|
-
setExecutionError(errorMsg);
|
|
9344
|
-
if (err instanceof TokenFlightError) {
|
|
9336
|
+
store.setFromToken(resolved);
|
|
9337
|
+
} catch (err) {
|
|
9345
9338
|
props.callbacks?.onSwapError?.({
|
|
9346
|
-
code:
|
|
9347
|
-
message: err.message
|
|
9348
|
-
details: err.details
|
|
9339
|
+
code: ErrorCode.INVALID_TOKEN_IDENTIFIER,
|
|
9340
|
+
message: `Failed to resolve fromToken: ${err instanceof Error ? err.message : String(err)}`
|
|
9349
9341
|
});
|
|
9350
|
-
}
|
|
9342
|
+
}
|
|
9343
|
+
}
|
|
9344
|
+
if (props.config.toToken) {
|
|
9345
|
+
try {
|
|
9346
|
+
const target2 = parseTokenIdentifier(props.config.toToken);
|
|
9347
|
+
const resolved = await resolveToken(target2.chainId, target2.address, props.config.apiEndpoint, c);
|
|
9348
|
+
if (typeof resolved.decimals !== "number") {
|
|
9349
|
+
throw new TokenFlightError(ErrorCode.INVALID_TOKEN_IDENTIFIER, "Failed to resolve toToken metadata");
|
|
9350
|
+
}
|
|
9351
|
+
store.setToToken(resolved);
|
|
9352
|
+
} catch (err) {
|
|
9351
9353
|
props.callbacks?.onSwapError?.({
|
|
9352
|
-
code: ErrorCode.
|
|
9353
|
-
message: String(err)
|
|
9354
|
+
code: ErrorCode.INVALID_TOKEN_IDENTIFIER,
|
|
9355
|
+
message: `Failed to resolve toToken: ${err instanceof Error ? err.message : String(err)}`
|
|
9354
9356
|
});
|
|
9355
9357
|
}
|
|
9356
9358
|
}
|
|
9357
|
-
};
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
setTrackingOrderId(null);
|
|
9369
|
-
setTrackingProviderName(null);
|
|
9370
|
-
setTrackingProviderIcon(null);
|
|
9371
|
-
setExecutionError(null);
|
|
9372
|
-
queryClient.removeQueries({
|
|
9373
|
-
queryKey: ["quote", client().baseUrl]
|
|
9374
|
-
});
|
|
9375
|
-
queryClient.removeQueries({
|
|
9376
|
-
queryKey: ["order", client().baseUrl]
|
|
9359
|
+
});
|
|
9360
|
+
onMount(() => {
|
|
9361
|
+
if (props.config.recipient) {
|
|
9362
|
+
store.setRecipient(props.config.recipient);
|
|
9363
|
+
}
|
|
9364
|
+
});
|
|
9365
|
+
const handleAmountChange = (amount2) => {
|
|
9366
|
+
store.setInputAmount(amount2);
|
|
9367
|
+
props.callbacks?.onAmountChanged?.({
|
|
9368
|
+
amount: amount2,
|
|
9369
|
+
direction: "from"
|
|
9377
9370
|
});
|
|
9378
|
-
|
|
9371
|
+
if (store.error()) store.clearError();
|
|
9372
|
+
setDebouncedAmount(amount2);
|
|
9379
9373
|
};
|
|
9380
9374
|
const handleTokenSelect = (token) => {
|
|
9381
9375
|
const resolved = {
|
|
@@ -9388,43 +9382,29 @@ function SwapComponent(props) {
|
|
|
9388
9382
|
priceUsd: token.priceUsd
|
|
9389
9383
|
};
|
|
9390
9384
|
if (selectorOpen() === "from") {
|
|
9391
|
-
|
|
9385
|
+
store.setFromToken(resolved);
|
|
9392
9386
|
} else {
|
|
9393
|
-
|
|
9387
|
+
store.setToToken(resolved);
|
|
9394
9388
|
}
|
|
9395
9389
|
setSelectorOpen(null);
|
|
9396
|
-
const amount2 = sm.state().inputAmount;
|
|
9397
|
-
if (!amount2 || parseFloat(amount2) <= 0) {
|
|
9398
|
-
sm.clearRoutes();
|
|
9399
|
-
sm.setOutputAmount("");
|
|
9400
|
-
if (sm.state().phase !== "idle") {
|
|
9401
|
-
sm.transition("idle");
|
|
9402
|
-
}
|
|
9403
|
-
}
|
|
9404
9390
|
};
|
|
9405
9391
|
const handleSwapTokens = () => {
|
|
9406
|
-
|
|
9407
|
-
const
|
|
9408
|
-
const
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
if (phase2 === "success") {
|
|
9415
|
-
sm.transition("idle");
|
|
9416
|
-
}
|
|
9417
|
-
const amount2 = current.inputAmount;
|
|
9418
|
-
if (!amount2 || parseFloat(amount2) <= 0) {
|
|
9419
|
-
if (sm.state().phase !== "idle") {
|
|
9420
|
-
sm.transition("idle");
|
|
9421
|
-
}
|
|
9422
|
-
}
|
|
9392
|
+
if (isExecuting() || !store.fromToken() || !store.toToken()) return;
|
|
9393
|
+
const from = store.fromToken();
|
|
9394
|
+
const to = store.toToken();
|
|
9395
|
+
batch(() => {
|
|
9396
|
+
store.setFromToken(to);
|
|
9397
|
+
store.setToToken(from);
|
|
9398
|
+
if (store.execPhase() === "success") store.setExecPhase(null);
|
|
9399
|
+
});
|
|
9423
9400
|
};
|
|
9424
9401
|
const handleMaxClick = () => {
|
|
9425
|
-
const
|
|
9426
|
-
|
|
9427
|
-
|
|
9402
|
+
const from = store.fromToken();
|
|
9403
|
+
const balRaw = fromBalanceRaw();
|
|
9404
|
+
if (!from || typeof from.decimals !== "number" || !balRaw || balRaw === "0") return;
|
|
9405
|
+
const fullPrecision = toDisplayAmount(balRaw, from.decimals);
|
|
9406
|
+
if (fullPrecision && fullPrecision !== "0") {
|
|
9407
|
+
handleAmountChange(fullPrecision);
|
|
9428
9408
|
}
|
|
9429
9409
|
};
|
|
9430
9410
|
const handleAccountClick = async () => {
|
|
@@ -9435,20 +9415,12 @@ function SwapComponent(props) {
|
|
|
9435
9415
|
}
|
|
9436
9416
|
};
|
|
9437
9417
|
const truncateAddress = (addr) => `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
9438
|
-
const
|
|
9439
|
-
const
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
return p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking";
|
|
9445
|
-
};
|
|
9446
|
-
const state = sm.state;
|
|
9447
|
-
const bestRoute = () => {
|
|
9448
|
-
const s = sm.state();
|
|
9449
|
-
if (s.routes.length === 0) return null;
|
|
9450
|
-
return s.routes.find((r) => r.routeId === s.selectedRouteId) ?? s.routes[0] ?? null;
|
|
9451
|
-
};
|
|
9418
|
+
const quotePreviewRoute = createMemo(() => {
|
|
9419
|
+
const route = bestRoute();
|
|
9420
|
+
if (!route || !store.fromToken() || !store.toToken()) return null;
|
|
9421
|
+
if (phase() === "quoting" || showQuote()) return route;
|
|
9422
|
+
return null;
|
|
9423
|
+
});
|
|
9452
9424
|
const titleText = createMemo(() => {
|
|
9453
9425
|
const raw = props.config.titleText?.trim();
|
|
9454
9426
|
return raw && raw.length > 0 ? raw : "TokenFlight";
|
|
@@ -9461,23 +9433,11 @@ function SwapComponent(props) {
|
|
|
9461
9433
|
const raw = props.config.titleImageUrl?.trim();
|
|
9462
9434
|
return raw && raw.length > 0 ? raw : null;
|
|
9463
9435
|
});
|
|
9464
|
-
const isQuoteLoading = createMemo(() => {
|
|
9465
|
-
const s = sm.state();
|
|
9466
|
-
if (!s.fromToken || !s.toToken) return false;
|
|
9467
|
-
return s.phase === "quoting" && parseFloat(s.inputAmount) > 0 && s.routes.length === 0;
|
|
9468
|
-
});
|
|
9469
|
-
const quotePreviewRoute = createMemo(() => {
|
|
9470
|
-
const s = sm.state();
|
|
9471
|
-
const route = bestRoute();
|
|
9472
|
-
if (!route || !s.fromToken || !s.toToken) return null;
|
|
9473
|
-
if (s.phase === "quoting" || showQuote()) return route;
|
|
9474
|
-
return null;
|
|
9475
|
-
});
|
|
9476
9436
|
return (() => {
|
|
9477
9437
|
var _el$ = _tmpl$3$2(), _el$2 = _el$.firstChild;
|
|
9478
9438
|
insert(_el$, createComponent(Show, {
|
|
9479
9439
|
get when() {
|
|
9480
|
-
return memo(() =>
|
|
9440
|
+
return memo(() => phase() === "success")() && store.order();
|
|
9481
9441
|
},
|
|
9482
9442
|
get fallback() {
|
|
9483
9443
|
return createComponent(Show, {
|
|
@@ -9595,7 +9555,7 @@ function SwapComponent(props) {
|
|
|
9595
9555
|
}), null);
|
|
9596
9556
|
insert(_el$17, createComponent(AmountInput, {
|
|
9597
9557
|
get value() {
|
|
9598
|
-
return
|
|
9558
|
+
return store.inputAmount();
|
|
9599
9559
|
},
|
|
9600
9560
|
onChange: handleAmountChange,
|
|
9601
9561
|
get disabled() {
|
|
@@ -9604,7 +9564,7 @@ function SwapComponent(props) {
|
|
|
9604
9564
|
}), null);
|
|
9605
9565
|
insert(_el$17, createComponent(Show, {
|
|
9606
9566
|
get when() {
|
|
9607
|
-
return
|
|
9567
|
+
return store.fromToken();
|
|
9608
9568
|
},
|
|
9609
9569
|
get fallback() {
|
|
9610
9570
|
return (() => {
|
|
@@ -9633,21 +9593,21 @@ function SwapComponent(props) {
|
|
|
9633
9593
|
addEventListener(_el$18, "click", () => setSelectorOpen("from"));
|
|
9634
9594
|
insert(_el$19, createComponent(TokenIcon, {
|
|
9635
9595
|
get symbol() {
|
|
9636
|
-
return
|
|
9596
|
+
return store.fromToken().symbol ?? "?";
|
|
9637
9597
|
},
|
|
9638
9598
|
color: "#2775CA",
|
|
9639
9599
|
size: 24,
|
|
9640
9600
|
get logoURI() {
|
|
9641
|
-
return
|
|
9601
|
+
return store.fromToken().logoURI;
|
|
9642
9602
|
}
|
|
9643
9603
|
}), _el$20);
|
|
9644
9604
|
insert(_el$20, createComponent(ChainDot, {
|
|
9645
9605
|
size: 10,
|
|
9646
9606
|
get iconUrl() {
|
|
9647
|
-
return chainIconUrl(client().baseUrl,
|
|
9607
|
+
return chainIconUrl(client().baseUrl, store.fromToken().chainId);
|
|
9648
9608
|
}
|
|
9649
9609
|
}));
|
|
9650
|
-
insert(_el$21, () =>
|
|
9610
|
+
insert(_el$21, () => store.fromToken().symbol);
|
|
9651
9611
|
insert(_el$22, createComponent(chevron_down_default, {
|
|
9652
9612
|
size: 14
|
|
9653
9613
|
}));
|
|
@@ -9713,7 +9673,7 @@ function SwapComponent(props) {
|
|
|
9713
9673
|
insert(_el$30, () => t("swap.youReceive"));
|
|
9714
9674
|
insert(_el$29, createComponent(Show, {
|
|
9715
9675
|
get when() {
|
|
9716
|
-
return memo(() => !!isConnected())() &&
|
|
9676
|
+
return memo(() => !!isConnected())() && store.toToken();
|
|
9717
9677
|
},
|
|
9718
9678
|
get children() {
|
|
9719
9679
|
var _el$31 = _tmpl$1$2(), _el$32 = _el$31.firstChild;
|
|
@@ -9752,17 +9712,17 @@ function SwapComponent(props) {
|
|
|
9752
9712
|
var _el$34 = _tmpl$10$2();
|
|
9753
9713
|
insert(_el$34, createComponent(SignificantNumber, {
|
|
9754
9714
|
get value() {
|
|
9755
|
-
return memo(() => !!(showQuote() ||
|
|
9715
|
+
return memo(() => !!(showQuote() || phase() === "quoting"))() ? outputAmount() || "0" : "0";
|
|
9756
9716
|
},
|
|
9757
9717
|
digits: 8
|
|
9758
9718
|
}));
|
|
9759
|
-
createRenderEffect(() => className(_el$34, `${amountStyles.amount} ${!showQuote() &&
|
|
9719
|
+
createRenderEffect(() => className(_el$34, `${amountStyles.amount} ${!showQuote() && phase() !== "quoting" ? amountStyles.muted : ""}`));
|
|
9760
9720
|
return _el$34;
|
|
9761
9721
|
}
|
|
9762
9722
|
}), null);
|
|
9763
9723
|
insert(_el$33, createComponent(Show, {
|
|
9764
9724
|
get when() {
|
|
9765
|
-
return
|
|
9725
|
+
return store.toToken();
|
|
9766
9726
|
},
|
|
9767
9727
|
get fallback() {
|
|
9768
9728
|
return (() => {
|
|
@@ -9791,21 +9751,21 @@ function SwapComponent(props) {
|
|
|
9791
9751
|
addEventListener(_el$35, "click", () => setSelectorOpen("to"));
|
|
9792
9752
|
insert(_el$36, createComponent(TokenIcon, {
|
|
9793
9753
|
get symbol() {
|
|
9794
|
-
return
|
|
9754
|
+
return store.toToken().symbol ?? "?";
|
|
9795
9755
|
},
|
|
9796
9756
|
color: "#0052FF",
|
|
9797
9757
|
size: 24,
|
|
9798
9758
|
get logoURI() {
|
|
9799
|
-
return
|
|
9759
|
+
return store.toToken().logoURI;
|
|
9800
9760
|
}
|
|
9801
9761
|
}), _el$37);
|
|
9802
9762
|
insert(_el$37, createComponent(ChainDot, {
|
|
9803
9763
|
size: 10,
|
|
9804
9764
|
get iconUrl() {
|
|
9805
|
-
return chainIconUrl(client().baseUrl,
|
|
9765
|
+
return chainIconUrl(client().baseUrl, store.toToken().chainId);
|
|
9806
9766
|
}
|
|
9807
9767
|
}));
|
|
9808
|
-
insert(_el$38, () =>
|
|
9768
|
+
insert(_el$38, () => store.toToken().symbol);
|
|
9809
9769
|
insert(_el$39, createComponent(chevron_down_default, {
|
|
9810
9770
|
size: 14
|
|
9811
9771
|
}));
|
|
@@ -9857,7 +9817,7 @@ function SwapComponent(props) {
|
|
|
9857
9817
|
}
|
|
9858
9818
|
}), createComponent(Show, {
|
|
9859
9819
|
get when() {
|
|
9860
|
-
return memo(() => !!(quotePreviewRoute() &&
|
|
9820
|
+
return memo(() => !!(quotePreviewRoute() && store.fromToken()))() && store.toToken();
|
|
9861
9821
|
},
|
|
9862
9822
|
get children() {
|
|
9863
9823
|
var _el$42 = _tmpl$12$1();
|
|
@@ -9866,15 +9826,15 @@ function SwapComponent(props) {
|
|
|
9866
9826
|
return quotePreviewRoute();
|
|
9867
9827
|
},
|
|
9868
9828
|
get fromToken() {
|
|
9869
|
-
return
|
|
9829
|
+
return store.fromToken();
|
|
9870
9830
|
},
|
|
9871
9831
|
get toToken() {
|
|
9872
|
-
return
|
|
9832
|
+
return store.toToken();
|
|
9873
9833
|
},
|
|
9874
9834
|
inline: true,
|
|
9875
9835
|
countdownSeconds,
|
|
9876
9836
|
countdownTotal: QUOTE_REFRESH_SECONDS,
|
|
9877
|
-
showCountdown: () =>
|
|
9837
|
+
showCountdown: () => phase() === "quoted"
|
|
9878
9838
|
}));
|
|
9879
9839
|
createRenderEffect(() => className(_el$42, quoteStyles.quote));
|
|
9880
9840
|
return _el$42;
|
|
@@ -9903,7 +9863,7 @@ function SwapComponent(props) {
|
|
|
9903
9863
|
var _el$46 = _tmpl$14();
|
|
9904
9864
|
insert(_el$46, createComponent(ActionButton, {
|
|
9905
9865
|
get phase() {
|
|
9906
|
-
return
|
|
9866
|
+
return phase();
|
|
9907
9867
|
},
|
|
9908
9868
|
get isConnected() {
|
|
9909
9869
|
return isConnected();
|
|
@@ -9915,10 +9875,10 @@ function SwapComponent(props) {
|
|
|
9915
9875
|
onConfirm: handleConfirm,
|
|
9916
9876
|
onRetry: handleRetry,
|
|
9917
9877
|
get errorLabel() {
|
|
9918
|
-
return
|
|
9878
|
+
return store.error() ?? void 0;
|
|
9919
9879
|
},
|
|
9920
9880
|
get needsRecipient() {
|
|
9921
|
-
return memo(() => !!needRecipient())() && !
|
|
9881
|
+
return memo(() => !!needRecipient())() && !store.recipient();
|
|
9922
9882
|
},
|
|
9923
9883
|
onEnterRecipient: () => setRecipientEditorOpen(true),
|
|
9924
9884
|
get insufficientBalance() {
|
|
@@ -9932,13 +9892,13 @@ function SwapComponent(props) {
|
|
|
9932
9892
|
get children() {
|
|
9933
9893
|
return createComponent(OrderProgress, {
|
|
9934
9894
|
get order() {
|
|
9935
|
-
return
|
|
9895
|
+
return store.order();
|
|
9936
9896
|
},
|
|
9937
9897
|
get fromToken() {
|
|
9938
|
-
return
|
|
9898
|
+
return store.fromToken();
|
|
9939
9899
|
},
|
|
9940
9900
|
get toToken() {
|
|
9941
|
-
return
|
|
9901
|
+
return store.toToken();
|
|
9942
9902
|
},
|
|
9943
9903
|
get providerName() {
|
|
9944
9904
|
return trackingProviderName();
|
|
@@ -9950,10 +9910,10 @@ function SwapComponent(props) {
|
|
|
9950
9910
|
return props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
|
|
9951
9911
|
},
|
|
9952
9912
|
get inputAmount() {
|
|
9953
|
-
return
|
|
9913
|
+
return store.inputAmount();
|
|
9954
9914
|
},
|
|
9955
9915
|
get outputAmount() {
|
|
9956
|
-
return
|
|
9916
|
+
return outputAmount();
|
|
9957
9917
|
},
|
|
9958
9918
|
onNewSwap: handleNewSwap,
|
|
9959
9919
|
onRetry: handleRetry,
|
|
@@ -9974,13 +9934,13 @@ function SwapComponent(props) {
|
|
|
9974
9934
|
get children() {
|
|
9975
9935
|
return createComponent(TransactionComplete, {
|
|
9976
9936
|
get order() {
|
|
9977
|
-
return
|
|
9937
|
+
return store.order();
|
|
9978
9938
|
},
|
|
9979
9939
|
get fromToken() {
|
|
9980
|
-
return
|
|
9940
|
+
return store.fromToken();
|
|
9981
9941
|
},
|
|
9982
9942
|
get toToken() {
|
|
9983
|
-
return
|
|
9943
|
+
return store.toToken();
|
|
9984
9944
|
},
|
|
9985
9945
|
onNewSwap: handleNewSwap,
|
|
9986
9946
|
get apiEndpoint() {
|
|
@@ -10032,16 +9992,16 @@ function SwapComponent(props) {
|
|
|
10032
9992
|
}), null);
|
|
10033
9993
|
insert(_el$, createComponent(Show, {
|
|
10034
9994
|
get when() {
|
|
10035
|
-
return memo(() => !!recipientEditorOpen())() &&
|
|
9995
|
+
return memo(() => !!recipientEditorOpen())() && store.toToken();
|
|
10036
9996
|
},
|
|
10037
9997
|
get children() {
|
|
10038
9998
|
var _el$4 = _tmpl$2$2();
|
|
10039
9999
|
insert(_el$4, createComponent(RecipientEditor, {
|
|
10040
10000
|
get initialValue() {
|
|
10041
|
-
return
|
|
10001
|
+
return store.recipient() ?? "";
|
|
10042
10002
|
},
|
|
10043
10003
|
get chainType() {
|
|
10044
|
-
return getChainType(
|
|
10004
|
+
return getChainType(store.toToken().chainId);
|
|
10045
10005
|
},
|
|
10046
10006
|
onConfirm: (addr) => {
|
|
10047
10007
|
handleRecipientChange(addr);
|
|
@@ -10624,21 +10584,210 @@ function rankPayTokens(balances, targetSymbol, targetChainId, targetAddress, des
|
|
|
10624
10584
|
if (!hasEnoughGasOnChain(t2.address, t2.chainId, nativeBalanceByChain)) {
|
|
10625
10585
|
continue;
|
|
10626
10586
|
}
|
|
10627
|
-
const tier = getTier(
|
|
10628
|
-
{ symbol: t2.symbol, chainId: t2.chainId },
|
|
10629
|
-
{ symbol: targetSymbol, chainId: targetChainId }
|
|
10630
|
-
);
|
|
10631
|
-
candidates.push({
|
|
10632
|
-
token: t2,
|
|
10633
|
-
tier,
|
|
10634
|
-
gasCostScore: getChainGasCostScore(t2.chainId)
|
|
10587
|
+
const tier = getTier(
|
|
10588
|
+
{ symbol: t2.symbol, chainId: t2.chainId },
|
|
10589
|
+
{ symbol: targetSymbol, chainId: targetChainId }
|
|
10590
|
+
);
|
|
10591
|
+
candidates.push({
|
|
10592
|
+
token: t2,
|
|
10593
|
+
tier,
|
|
10594
|
+
gasCostScore: getChainGasCostScore(t2.chainId)
|
|
10595
|
+
});
|
|
10596
|
+
}
|
|
10597
|
+
candidates.sort((a, b) => {
|
|
10598
|
+
if (a.tier !== b.tier) return a.tier - b.tier;
|
|
10599
|
+
return a.gasCostScore - b.gasCostScore;
|
|
10600
|
+
});
|
|
10601
|
+
return candidates.map((c) => c.token);
|
|
10602
|
+
}
|
|
10603
|
+
function isSameToken$1(a, b) {
|
|
10604
|
+
return a.chainId === b.chainId && a.address.toLowerCase() === b.address.toLowerCase();
|
|
10605
|
+
}
|
|
10606
|
+
function useReceiveExecution(params) {
|
|
10607
|
+
const [trackingOrderId, setTrackingOrderId] = createSignal(
|
|
10608
|
+
null
|
|
10609
|
+
);
|
|
10610
|
+
const [trackingProviderName, setTrackingProviderName] = createSignal(null);
|
|
10611
|
+
const [trackingProviderIcon, setTrackingProviderIcon] = createSignal(null);
|
|
10612
|
+
const [trackingInputAmount, setTrackingInputAmount] = createSignal(null);
|
|
10613
|
+
const [executionError, setExecutionError] = createSignal(null);
|
|
10614
|
+
const handleConfirm = async () => {
|
|
10615
|
+
const selectedToken = params.selectedPayToken();
|
|
10616
|
+
const selected2 = selectedToken ? params.payTokenQuotes().find((quote2) => isSameToken$1(quote2.token, selectedToken)) : null;
|
|
10617
|
+
const addr = params.walletAddress();
|
|
10618
|
+
if (!selected2 || !params.client() || !params.walletAdapter() || !addr)
|
|
10619
|
+
return;
|
|
10620
|
+
if (params.needRecipient() && !params.recipient()) {
|
|
10621
|
+
params.setError("Recipient address is required for cross-chain swaps");
|
|
10622
|
+
params.setErrorCode(ErrorCode.INVALID_CONFIG);
|
|
10623
|
+
return;
|
|
10624
|
+
}
|
|
10625
|
+
const validBefore = selected2.route.quote.validBefore;
|
|
10626
|
+
if (validBefore && Date.now() / 1e3 > validBefore) {
|
|
10627
|
+
params.setLoadingQuotes(true);
|
|
10628
|
+
try {
|
|
10629
|
+
const target2 = params.targetToken();
|
|
10630
|
+
if (!target2 || typeof target2.decimals !== "number") return;
|
|
10631
|
+
const baseAmount = toBaseUnits(params.configAmount(), target2.decimals);
|
|
10632
|
+
const refreshed = await params.fetchSingleQuote(
|
|
10633
|
+
params.client(),
|
|
10634
|
+
selected2.token,
|
|
10635
|
+
baseAmount,
|
|
10636
|
+
addr,
|
|
10637
|
+
target2,
|
|
10638
|
+
params.recipient()
|
|
10639
|
+
);
|
|
10640
|
+
if (refreshed) {
|
|
10641
|
+
const updated = [...params.payTokenQuotes()];
|
|
10642
|
+
const existingIdx = updated.findIndex(
|
|
10643
|
+
(quote2) => isSameToken$1(quote2.token, selected2.token)
|
|
10644
|
+
);
|
|
10645
|
+
if (existingIdx >= 0) {
|
|
10646
|
+
updated[existingIdx] = refreshed;
|
|
10647
|
+
} else {
|
|
10648
|
+
updated.push(refreshed);
|
|
10649
|
+
}
|
|
10650
|
+
params.setPayTokenQuotes(updated);
|
|
10651
|
+
} else {
|
|
10652
|
+
params.setError("Quote expired and could not be refreshed");
|
|
10653
|
+
params.setErrorCode(ErrorCode.QUOTE_EXPIRED);
|
|
10654
|
+
return;
|
|
10655
|
+
}
|
|
10656
|
+
} catch {
|
|
10657
|
+
params.setError("Quote expired and could not be refreshed");
|
|
10658
|
+
params.setErrorCode(ErrorCode.QUOTE_EXPIRED);
|
|
10659
|
+
return;
|
|
10660
|
+
} finally {
|
|
10661
|
+
params.setLoadingQuotes(false);
|
|
10662
|
+
}
|
|
10663
|
+
}
|
|
10664
|
+
const confirmedToken = params.selectedPayToken();
|
|
10665
|
+
const confirmedQuote = confirmedToken ? params.payTokenQuotes().find((quote2) => isSameToken$1(quote2.token, confirmedToken)) : null;
|
|
10666
|
+
if (!confirmedQuote) return;
|
|
10667
|
+
params.setFromToken({
|
|
10668
|
+
chainId: confirmedQuote.token.chainId,
|
|
10669
|
+
address: confirmedQuote.token.address,
|
|
10670
|
+
symbol: confirmedQuote.token.symbol,
|
|
10671
|
+
name: confirmedQuote.token.name,
|
|
10672
|
+
decimals: confirmedQuote.token.decimals,
|
|
10673
|
+
logoURI: confirmedQuote.token.logoURI
|
|
10674
|
+
});
|
|
10675
|
+
setTrackingProviderName(confirmedQuote.route.routeId ?? null);
|
|
10676
|
+
const apiBase = params.apiEndpoint() ?? DEFAULT_API_ENDPOINT;
|
|
10677
|
+
setTrackingProviderIcon(
|
|
10678
|
+
confirmedQuote.route.icon ? `${apiBase}${confirmedQuote.route.icon}` : null
|
|
10679
|
+
);
|
|
10680
|
+
setTrackingInputAmount(
|
|
10681
|
+
toDisplayAmount(
|
|
10682
|
+
confirmedQuote.route.quote.amountIn,
|
|
10683
|
+
confirmedQuote.token.decimals
|
|
10684
|
+
)
|
|
10685
|
+
);
|
|
10686
|
+
setExecutionError(null);
|
|
10687
|
+
params.setExecPhase("building");
|
|
10688
|
+
try {
|
|
10689
|
+
const depositData = await params.client().buildDeposit({
|
|
10690
|
+
from: addr,
|
|
10691
|
+
quoteId: confirmedQuote.quoteId,
|
|
10692
|
+
routeId: confirmedQuote.route.routeId
|
|
10693
|
+
});
|
|
10694
|
+
params.setExecPhase("awaiting-wallet");
|
|
10695
|
+
let txHash;
|
|
10696
|
+
if (depositData.kind === "CONTRACT_CALL" && depositData.approvals) {
|
|
10697
|
+
for (const approval of depositData.approvals) {
|
|
10698
|
+
if (approval.type === "eip1193_request") {
|
|
10699
|
+
const result = await params.walletAdapter().executeWalletAction({
|
|
10700
|
+
type: "eip1193_request",
|
|
10701
|
+
chainId: confirmedQuote.token.chainId,
|
|
10702
|
+
method: approval.request.method,
|
|
10703
|
+
params: approval.request.params
|
|
10704
|
+
});
|
|
10705
|
+
if (!result.success) {
|
|
10706
|
+
throw new TokenFlightError(
|
|
10707
|
+
ErrorCode.WALLET_ACTION_FAILED,
|
|
10708
|
+
result.error ?? "Wallet action failed"
|
|
10709
|
+
);
|
|
10710
|
+
}
|
|
10711
|
+
if (approval.deposit) txHash = result.txHash ?? txHash;
|
|
10712
|
+
} else if (approval.type === "solana_sendTransaction") {
|
|
10713
|
+
const result = await params.walletAdapter().executeWalletAction({
|
|
10714
|
+
type: "solana_signAndSendTransaction",
|
|
10715
|
+
transaction: approval.transaction
|
|
10716
|
+
});
|
|
10717
|
+
if (!result.success) {
|
|
10718
|
+
throw new TokenFlightError(
|
|
10719
|
+
ErrorCode.WALLET_ACTION_FAILED,
|
|
10720
|
+
result.error ?? "Wallet action failed"
|
|
10721
|
+
);
|
|
10722
|
+
}
|
|
10723
|
+
if (approval.deposit) txHash = result.txHash ?? txHash;
|
|
10724
|
+
}
|
|
10725
|
+
}
|
|
10726
|
+
}
|
|
10727
|
+
if (!txHash) {
|
|
10728
|
+
throw new TokenFlightError(
|
|
10729
|
+
ErrorCode.TRANSACTION_FAILED,
|
|
10730
|
+
"No deposit transaction hash received"
|
|
10731
|
+
);
|
|
10732
|
+
}
|
|
10733
|
+
params.setExecPhase("submitting");
|
|
10734
|
+
const submitResult = await params.client().submitDeposit({
|
|
10735
|
+
quoteId: confirmedQuote.quoteId,
|
|
10736
|
+
routeId: confirmedQuote.route.routeId,
|
|
10737
|
+
txHash
|
|
10738
|
+
});
|
|
10739
|
+
params.setExecPhase("tracking");
|
|
10740
|
+
setTrackingOrderId(submitResult.orderId);
|
|
10741
|
+
} catch (err) {
|
|
10742
|
+
const errorMsg = err instanceof Error ? err.message : typeof err === "string" ? err : "Transaction failed";
|
|
10743
|
+
setExecutionError(errorMsg);
|
|
10744
|
+
if (err instanceof TokenFlightError) {
|
|
10745
|
+
params.callbacks()?.onSwapError?.({
|
|
10746
|
+
code: err.code,
|
|
10747
|
+
message: err.message,
|
|
10748
|
+
details: err.details
|
|
10749
|
+
});
|
|
10750
|
+
} else {
|
|
10751
|
+
params.callbacks()?.onSwapError?.({
|
|
10752
|
+
code: ErrorCode.TRANSACTION_FAILED,
|
|
10753
|
+
message: String(err)
|
|
10754
|
+
});
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
};
|
|
10758
|
+
const handleRetry = () => {
|
|
10759
|
+
batch(() => {
|
|
10760
|
+
setExecutionError(null);
|
|
10761
|
+
params.setExecPhase(null);
|
|
10762
|
+
params.storeClearError();
|
|
10763
|
+
params.setPayTokenQuotes([]);
|
|
10635
10764
|
});
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
|
|
10765
|
+
params.onRetry?.();
|
|
10766
|
+
};
|
|
10767
|
+
const handleNewSwap = () => {
|
|
10768
|
+
batch(() => {
|
|
10769
|
+
params.storeReset();
|
|
10770
|
+
setTrackingOrderId(null);
|
|
10771
|
+
setTrackingProviderName(null);
|
|
10772
|
+
setTrackingProviderIcon(null);
|
|
10773
|
+
setTrackingInputAmount(null);
|
|
10774
|
+
setExecutionError(null);
|
|
10775
|
+
params.setPayTokenQuotes([]);
|
|
10776
|
+
});
|
|
10777
|
+
queryClient.removeQueries({ queryKey: ["quote", params.client().baseUrl] });
|
|
10778
|
+
queryClient.removeQueries({ queryKey: ["order", params.client().baseUrl] });
|
|
10779
|
+
params.onReset?.();
|
|
10780
|
+
};
|
|
10781
|
+
return {
|
|
10782
|
+
trackingOrderId,
|
|
10783
|
+
trackingProviderName,
|
|
10784
|
+
trackingProviderIcon,
|
|
10785
|
+
trackingInputAmount,
|
|
10786
|
+
executionError,
|
|
10787
|
+
handleConfirm,
|
|
10788
|
+
handleRetry,
|
|
10789
|
+
handleNewSwap
|
|
10790
|
+
};
|
|
10642
10791
|
}
|
|
10643
10792
|
const header = "tf-9b71d6";
|
|
10644
10793
|
const section = "tf-4c9136";
|
|
@@ -10661,24 +10810,40 @@ const styles = {
|
|
|
10661
10810
|
fiat
|
|
10662
10811
|
};
|
|
10663
10812
|
var _tmpl$$1 = /* @__PURE__ */ template(`<div data-testid=selector-overlay>`), _tmpl$2 = /* @__PURE__ */ template(`<div>`), _tmpl$3 = /* @__PURE__ */ template(`<div part=container><div part=accent-line data-testid=accent-line>`), _tmpl$4 = /* @__PURE__ */ template(`<img width=22 height=22>`), _tmpl$5 = /* @__PURE__ */ template(`<button part=wallet-info><div data-testid=wallet-dot></div><span data-testid=wallet-address>`), _tmpl$6 = /* @__PURE__ */ template(`<div part=header><div><span data-testid=header-title>`), _tmpl$7 = /* @__PURE__ */ template(`<button part=recipient-badge data-testid=recipient-badge><span>`), _tmpl$8 = /* @__PURE__ */ template(`<div><div data-testid=receive-section-label style=display:flex;justify-content:space-between;align-items:center><span></span></div><div part=target-token><div data-testid=receive-target-icon></div><span data-testid=receive-amount></span><span data-testid=receive-symbol></span><span>`), _tmpl$9 = /* @__PURE__ */ template(`<div style="padding:0 20px"><div>`), _tmpl$0 = /* @__PURE__ */ template(`<div part=price-preview data-testid=quote>`), _tmpl$1 = /* @__PURE__ */ template(`<div part=cta-wrapper>`), _tmpl$10 = /* @__PURE__ */ template(`<span>Flight`), _tmpl$11 = /* @__PURE__ */ template(`<div style="padding:0 20px"><div><div><div></div><div><div></div><div></div></div></div><div><div></div><div>`), _tmpl$12 = /* @__PURE__ */ template(`<div part=no-offer><div><svg width=28 height=28 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><circle cx=11 cy=11 r=8></circle><path d="m21 21-4.35-4.35"></path><path d="M8 11h6"></path></svg></div><span>`);
|
|
10813
|
+
function normalizeTokenAddress(address) {
|
|
10814
|
+
if (isNativeToken(address) && (address.startsWith("0x") || address.startsWith("0X"))) {
|
|
10815
|
+
return "0x0000000000000000000000000000000000000000";
|
|
10816
|
+
}
|
|
10817
|
+
return address.toLowerCase();
|
|
10818
|
+
}
|
|
10664
10819
|
function isSameToken(a, b) {
|
|
10665
|
-
return a.chainId === b.chainId && a.address
|
|
10820
|
+
return a.chainId === b.chainId && normalizeTokenAddress(a.address) === normalizeTokenAddress(b.address);
|
|
10666
10821
|
}
|
|
10667
10822
|
function ReceiveComponent(props) {
|
|
10668
|
-
const
|
|
10823
|
+
const store = createReceiveStore();
|
|
10669
10824
|
const [selectedPayIndex, setSelectedPayIndex] = createSignal(0);
|
|
10670
10825
|
const [payTokenSelectorOpen, setPayTokenSelectorOpen] = createSignal(false);
|
|
10671
10826
|
const [selectorOpen, setSelectorOpen] = createSignal(false);
|
|
10672
|
-
const [isConnected, setIsConnected] = createSignal(false);
|
|
10673
|
-
const [walletAddress2, setWalletAddress] = createSignal(null);
|
|
10674
10827
|
const [payTokenQuotes, setPayTokenQuotes] = createSignal([]);
|
|
10675
10828
|
const [loadingQuotes, setLoadingQuotes] = createSignal(false);
|
|
10676
|
-
const [trackingOrderId, setTrackingOrderId] = createSignal(null);
|
|
10677
|
-
const [trackingProviderName, setTrackingProviderName] = createSignal(null);
|
|
10678
|
-
const [trackingProviderIcon, setTrackingProviderIcon] = createSignal(null);
|
|
10679
|
-
const [trackingInputAmount, setTrackingInputAmount] = createSignal(null);
|
|
10680
|
-
const [executionError, setExecutionError] = createSignal(null);
|
|
10681
10829
|
const [selectedPayToken, setSelectedPayToken] = createSignal(null);
|
|
10830
|
+
const {
|
|
10831
|
+
isConnected,
|
|
10832
|
+
walletAddress: walletAddress2,
|
|
10833
|
+
handleConnect
|
|
10834
|
+
} = useWalletConnection({
|
|
10835
|
+
walletAdapter: () => props.walletAdapter,
|
|
10836
|
+
callbacks: () => props.callbacks,
|
|
10837
|
+
onAddressChange: (addr) => store.setWalletAddress(addr),
|
|
10838
|
+
onDisconnect: () => {
|
|
10839
|
+
setPayTokenQuotes([]);
|
|
10840
|
+
setSelectedPayToken(null);
|
|
10841
|
+
},
|
|
10842
|
+
onConnectError: (msg, code) => {
|
|
10843
|
+
store.setError(msg);
|
|
10844
|
+
store.setErrorCode(code);
|
|
10845
|
+
}
|
|
10846
|
+
});
|
|
10682
10847
|
const client = createMemo(() => {
|
|
10683
10848
|
const endpoint = props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
|
|
10684
10849
|
return new HyperstreamApi({
|
|
@@ -10686,79 +10851,35 @@ function ReceiveComponent(props) {
|
|
|
10686
10851
|
});
|
|
10687
10852
|
});
|
|
10688
10853
|
const apiBase = () => client().baseUrl;
|
|
10689
|
-
const
|
|
10690
|
-
const
|
|
10854
|
+
const phase = createMemo(() => deriveReceivePhase(store.execPhase(), store.error(), loadingQuotes(), payTokenQuotes().length));
|
|
10855
|
+
const isExecuting = createMemo(() => {
|
|
10856
|
+
const p = phase();
|
|
10857
|
+
return p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking";
|
|
10858
|
+
});
|
|
10691
10859
|
const [recipientEditorOpen, setRecipientEditorOpen] = createSignal(false);
|
|
10692
|
-
const recipientR = createMemo(() => sm.state().recipient);
|
|
10693
10860
|
const recipientLocked = createMemo(() => !!props.config.recipient);
|
|
10694
|
-
const
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10861
|
+
const {
|
|
10862
|
+
needRecipient,
|
|
10863
|
+
recipientDisplay,
|
|
10864
|
+
handleRecipientChange
|
|
10865
|
+
} = useRecipient({
|
|
10866
|
+
fromToken: selectedPayToken,
|
|
10867
|
+
toToken: store.targetToken,
|
|
10868
|
+
recipient: store.recipient,
|
|
10869
|
+
isConnected,
|
|
10870
|
+
walletAddress: walletAddress2,
|
|
10871
|
+
walletAdapter: () => props.walletAdapter,
|
|
10872
|
+
setRecipient: store.setRecipient
|
|
10705
10873
|
});
|
|
10706
|
-
const handleRecipientChange = (value2) => {
|
|
10707
|
-
const trimmed = value2.trim() || null;
|
|
10708
|
-
sm.setRecipient(trimmed);
|
|
10709
|
-
};
|
|
10710
10874
|
const balancesQuery = createTokenBalancesQuery(client, walletAddress2, () => isConnected() && !!walletAddress2(), () => props.walletAdapter?.supportedChainIds);
|
|
10711
|
-
const orderQuery = createOrderQuery(client, walletAddress2, trackingOrderId, () => phase() === "tracking" && !!trackingOrderId());
|
|
10712
|
-
createEffect(on(() => orderQuery.data, (order) => {
|
|
10713
|
-
if (!order || phase() !== "tracking") return;
|
|
10714
|
-
sm.setOrder(order);
|
|
10715
|
-
if (order.status === "failed" || order.status === "refunded") {
|
|
10716
|
-
queryClient.invalidateQueries({
|
|
10717
|
-
queryKey: ["tokenBalances", client().baseUrl]
|
|
10718
|
-
});
|
|
10719
|
-
props.callbacks?.onSwapError?.({
|
|
10720
|
-
code: ErrorCode.ORDER_FAILED,
|
|
10721
|
-
message: "Order " + order.status
|
|
10722
|
-
});
|
|
10723
|
-
return;
|
|
10724
|
-
}
|
|
10725
|
-
if (order.status === "filled") {
|
|
10726
|
-
sm.transition("success");
|
|
10727
|
-
queryClient.invalidateQueries({
|
|
10728
|
-
queryKey: ["tokenBalances", client().baseUrl]
|
|
10729
|
-
});
|
|
10730
|
-
const selected2 = selectedPayToken();
|
|
10731
|
-
props.callbacks?.onSwapSuccess?.({
|
|
10732
|
-
orderId: order.id,
|
|
10733
|
-
fromToken: selected2?.symbol ?? "",
|
|
10734
|
-
toToken: sm.state().targetToken?.symbol ?? "",
|
|
10735
|
-
fromAmount: order.srcAmount,
|
|
10736
|
-
toAmount: order.destAmount,
|
|
10737
|
-
txHash: order.depositTxHash
|
|
10738
|
-
});
|
|
10739
|
-
}
|
|
10740
|
-
}));
|
|
10741
10875
|
onMount(() => {
|
|
10742
10876
|
if (props.config.locale) {
|
|
10743
10877
|
setLocale(props.config.locale);
|
|
10744
10878
|
}
|
|
10745
10879
|
if (props.config.recipient) {
|
|
10746
|
-
|
|
10880
|
+
store.setRecipient(props.config.recipient);
|
|
10747
10881
|
}
|
|
10748
10882
|
});
|
|
10749
|
-
createEffect(on(needRecipient, (need) => {
|
|
10750
|
-
if (need && !sm.state().recipient && props.walletAdapter) {
|
|
10751
|
-
const target2 = sm.state().targetToken;
|
|
10752
|
-
if (!target2) return;
|
|
10753
|
-
const targetChainType = getChainType(target2.chainId);
|
|
10754
|
-
props.walletAdapter.getAddress(targetChainType).then((addr) => {
|
|
10755
|
-
if (addr && isAddressForChainType(addr, targetChainType) && !sm.state().recipient && needRecipient()) {
|
|
10756
|
-
sm.setRecipient(addr);
|
|
10757
|
-
}
|
|
10758
|
-
}).catch(() => {
|
|
10759
|
-
});
|
|
10760
|
-
}
|
|
10761
|
-
}));
|
|
10762
10883
|
const chainsQuery = createChainsQuery(client, () => true);
|
|
10763
10884
|
const chainMap = createMemo(() => {
|
|
10764
10885
|
const data = chainsQuery.data;
|
|
@@ -10768,18 +10889,20 @@ function ReceiveComponent(props) {
|
|
|
10768
10889
|
const c = client();
|
|
10769
10890
|
const amount2 = Number(props.config.amount);
|
|
10770
10891
|
if (!Number.isFinite(amount2) || amount2 <= 0) {
|
|
10771
|
-
|
|
10892
|
+
store.setError("Invalid amount: must be greater than zero");
|
|
10893
|
+
store.setErrorCode(ErrorCode.INVALID_AMOUNT);
|
|
10772
10894
|
return;
|
|
10773
10895
|
}
|
|
10774
10896
|
try {
|
|
10775
10897
|
const target2 = parseTokenIdentifier(props.config.target);
|
|
10776
10898
|
const resolved = await resolveToken(target2.chainId, target2.address, props.config.apiEndpoint, c);
|
|
10777
10899
|
if (typeof resolved.decimals !== "number") {
|
|
10778
|
-
|
|
10900
|
+
store.setError("Failed to resolve target token metadata");
|
|
10901
|
+
store.setErrorCode(ErrorCode.INVALID_CONFIG);
|
|
10779
10902
|
return;
|
|
10780
10903
|
}
|
|
10781
|
-
|
|
10782
|
-
|
|
10904
|
+
store.setTargetToken(resolved);
|
|
10905
|
+
store.setTargetAmount(props.config.amount);
|
|
10783
10906
|
if (props.config.fromToken) {
|
|
10784
10907
|
try {
|
|
10785
10908
|
const fromTarget = parseTokenIdentifier(props.config.fromToken);
|
|
@@ -10809,60 +10932,13 @@ function ReceiveComponent(props) {
|
|
|
10809
10932
|
}
|
|
10810
10933
|
}
|
|
10811
10934
|
} catch (err) {
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
});
|
|
10815
|
-
const detectChainType = () => {
|
|
10816
|
-
if (!props.walletAdapter) return "evm";
|
|
10817
|
-
return props.walletAdapter.supportedActionTypes.some((t2) => t2.startsWith("solana_")) ? "solana" : "evm";
|
|
10818
|
-
};
|
|
10819
|
-
onMount(async () => {
|
|
10820
|
-
if (props.walletAdapter) {
|
|
10821
|
-
const connected = props.walletAdapter.isConnected();
|
|
10822
|
-
setIsConnected(connected);
|
|
10823
|
-
if (connected) {
|
|
10824
|
-
const addr = await props.walletAdapter.getAddress();
|
|
10825
|
-
setWalletAddress(addr);
|
|
10826
|
-
sm.setWalletAddress(addr);
|
|
10827
|
-
props.callbacks?.onWalletConnected?.({
|
|
10828
|
-
address: addr ?? "",
|
|
10829
|
-
chainType: detectChainType()
|
|
10830
|
-
});
|
|
10831
|
-
}
|
|
10832
|
-
const handleWalletConnect = async () => {
|
|
10833
|
-
const addr = await props.walletAdapter.getAddress();
|
|
10834
|
-
if (isConnected() && walletAddress2() === addr) return;
|
|
10835
|
-
batch(() => {
|
|
10836
|
-
setIsConnected(true);
|
|
10837
|
-
setWalletAddress(addr);
|
|
10838
|
-
sm.setWalletAddress(addr);
|
|
10839
|
-
});
|
|
10840
|
-
props.callbacks?.onWalletConnected?.({
|
|
10841
|
-
address: addr ?? "",
|
|
10842
|
-
chainType: detectChainType()
|
|
10843
|
-
});
|
|
10844
|
-
};
|
|
10845
|
-
const handleWalletDisconnect = () => {
|
|
10846
|
-
if (!isConnected()) return;
|
|
10847
|
-
batch(() => {
|
|
10848
|
-
setIsConnected(false);
|
|
10849
|
-
setWalletAddress(null);
|
|
10850
|
-
sm.setWalletAddress(null);
|
|
10851
|
-
});
|
|
10852
|
-
setPayTokenQuotes([]);
|
|
10853
|
-
setSelectedPayToken(null);
|
|
10854
|
-
};
|
|
10855
|
-
props.walletAdapter.on("connect", handleWalletConnect);
|
|
10856
|
-
props.walletAdapter.on("disconnect", handleWalletDisconnect);
|
|
10857
|
-
onCleanup(() => {
|
|
10858
|
-
props.walletAdapter.off("connect", handleWalletConnect);
|
|
10859
|
-
props.walletAdapter.off("disconnect", handleWalletDisconnect);
|
|
10860
|
-
});
|
|
10935
|
+
store.setError(err instanceof Error ? err.message : "Failed to resolve target token");
|
|
10936
|
+
store.setErrorCode(ErrorCode.INVALID_CONFIG);
|
|
10861
10937
|
}
|
|
10862
10938
|
});
|
|
10863
10939
|
const balancePayTokens = createMemo(() => {
|
|
10864
10940
|
const data = balancesQuery.data;
|
|
10865
|
-
const target2 = targetToken();
|
|
10941
|
+
const target2 = store.targetToken();
|
|
10866
10942
|
if (!data || data.length === 0 || !target2) return [];
|
|
10867
10943
|
const supported = props.walletAdapter?.supportedChainIds;
|
|
10868
10944
|
const filtered = supported?.length ? data.filter((t2) => supported.includes(t2.chainId)) : data;
|
|
@@ -10872,7 +10948,7 @@ function ReceiveComponent(props) {
|
|
|
10872
10948
|
return rankPayTokens(filtered, target2.symbol ?? "", target2.chainId, target2.address, desiredUsdAmount > 0 ? desiredUsdAmount : void 0);
|
|
10873
10949
|
});
|
|
10874
10950
|
createEffect(on(balancePayTokens, (tokens) => {
|
|
10875
|
-
const p =
|
|
10951
|
+
const p = phase();
|
|
10876
10952
|
if (tokens.length > 0 && (p === "idle" || p === "error")) {
|
|
10877
10953
|
fetchPayTokenQuotes(tokens);
|
|
10878
10954
|
}
|
|
@@ -10880,9 +10956,9 @@ function ReceiveComponent(props) {
|
|
|
10880
10956
|
const selectedQuoteRequest = createMemo(() => {
|
|
10881
10957
|
const token = selectedPayToken();
|
|
10882
10958
|
if (!token) return null;
|
|
10883
|
-
const target2 = targetToken();
|
|
10959
|
+
const target2 = store.targetToken();
|
|
10884
10960
|
const addr = walletAddress2();
|
|
10885
|
-
const recipient =
|
|
10961
|
+
const recipient = store.recipient();
|
|
10886
10962
|
if (!target2 || typeof target2.decimals !== "number" || !addr) return null;
|
|
10887
10963
|
if (needRecipient() && !recipient) return null;
|
|
10888
10964
|
return {
|
|
@@ -10925,25 +11001,15 @@ function ReceiveComponent(props) {
|
|
|
10925
11001
|
}
|
|
10926
11002
|
}
|
|
10927
11003
|
}));
|
|
10928
|
-
const
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
11004
|
+
const {
|
|
11005
|
+
countdownSeconds
|
|
11006
|
+
} = useQuoteCountdown({
|
|
11007
|
+
phase,
|
|
11008
|
+
onExpired: () => {
|
|
11009
|
+
selectedQuoteQuery.refetch();
|
|
10933
11010
|
}
|
|
10934
|
-
setCountdownSeconds(QUOTE_REFRESH_SECONDS);
|
|
10935
|
-
const timer = setInterval(() => {
|
|
10936
|
-
setCountdownSeconds((prev) => {
|
|
10937
|
-
if (prev <= 1) {
|
|
10938
|
-
selectedQuoteQuery.refetch();
|
|
10939
|
-
return QUOTE_REFRESH_SECONDS;
|
|
10940
|
-
}
|
|
10941
|
-
return prev - 1;
|
|
10942
|
-
});
|
|
10943
|
-
}, 1e3);
|
|
10944
|
-
onCleanup(() => clearInterval(timer));
|
|
10945
11011
|
});
|
|
10946
|
-
const fetchSingleQuote = async (c, payToken, baseAmount, addr, target2, recipient) => {
|
|
11012
|
+
const fetchSingleQuote = async (c, payToken, baseAmount, addr, target2, recipient, signal) => {
|
|
10947
11013
|
try {
|
|
10948
11014
|
const request = {
|
|
10949
11015
|
tradeType: "EXACT_OUTPUT",
|
|
@@ -10957,9 +11023,11 @@ function ReceiveComponent(props) {
|
|
|
10957
11023
|
recipient
|
|
10958
11024
|
}
|
|
10959
11025
|
};
|
|
10960
|
-
const quoteResp = await queryClient.
|
|
11026
|
+
const quoteResp = await queryClient.fetchQuery({
|
|
10961
11027
|
queryKey: ["quote", c.baseUrl, request],
|
|
10962
|
-
queryFn: (
|
|
11028
|
+
queryFn: ({
|
|
11029
|
+
signal: querySignal
|
|
11030
|
+
}) => c.getQuotes(request, signal ?? querySignal),
|
|
10963
11031
|
staleTime: 15e3
|
|
10964
11032
|
});
|
|
10965
11033
|
if (quoteResp.routes.length > 0) {
|
|
@@ -10982,13 +11050,10 @@ function ReceiveComponent(props) {
|
|
|
10982
11050
|
const fetchPayTokenQuotes = async (tokensToQuote) => {
|
|
10983
11051
|
const c = client();
|
|
10984
11052
|
const addr = walletAddress2();
|
|
10985
|
-
const target2 =
|
|
11053
|
+
const target2 = store.targetToken();
|
|
10986
11054
|
if (!c || !addr || !target2 || typeof target2.decimals !== "number" || tokensToQuote.length === 0) return;
|
|
10987
|
-
|
|
10988
|
-
if (
|
|
10989
|
-
if (phase2 === "error") sm.transition("idle");
|
|
10990
|
-
sm.transition("quoting");
|
|
10991
|
-
}
|
|
11055
|
+
if (payTokenQuotes().length > 0) setPayTokenQuotes([]);
|
|
11056
|
+
if (store.error()) store.clearError();
|
|
10992
11057
|
setLoadingQuotes(true);
|
|
10993
11058
|
fetchAbortController?.abort();
|
|
10994
11059
|
const abortController = new AbortController();
|
|
@@ -11000,7 +11065,7 @@ function ReceiveComponent(props) {
|
|
|
11000
11065
|
const orderedTokens = preferredToken ? [preferredToken, ...tokensToQuote.filter((token) => !isSameToken(token, preferredToken))] : tokensToQuote;
|
|
11001
11066
|
for (const payToken of orderedTokens) {
|
|
11002
11067
|
if (abortController.signal.aborted) return;
|
|
11003
|
-
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2,
|
|
11068
|
+
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2, store.recipient(), abortController.signal);
|
|
11004
11069
|
if (abortController.signal.aborted) return;
|
|
11005
11070
|
if (quote2) {
|
|
11006
11071
|
setPayTokenQuotes([quote2]);
|
|
@@ -11008,18 +11073,13 @@ function ReceiveComponent(props) {
|
|
|
11008
11073
|
setSelectedPayIndex(index >= 0 ? index : 0);
|
|
11009
11074
|
setSelectedPayToken(payToken);
|
|
11010
11075
|
setLoadingQuotes(false);
|
|
11011
|
-
sm.transition("quoted");
|
|
11012
11076
|
return;
|
|
11013
11077
|
}
|
|
11014
11078
|
}
|
|
11015
11079
|
if (!abortController.signal.aborted) {
|
|
11016
11080
|
setPayTokenQuotes([]);
|
|
11017
|
-
sm.transition("idle");
|
|
11018
11081
|
}
|
|
11019
11082
|
} catch {
|
|
11020
|
-
if (!abortController.signal.aborted) {
|
|
11021
|
-
sm.transition("idle");
|
|
11022
|
-
}
|
|
11023
11083
|
} finally {
|
|
11024
11084
|
setLoadingQuotes(false);
|
|
11025
11085
|
}
|
|
@@ -11030,7 +11090,7 @@ function ReceiveComponent(props) {
|
|
|
11030
11090
|
const paymentTokens = createMemo(() => {
|
|
11031
11091
|
const tokens = balancePayTokens();
|
|
11032
11092
|
const quotes = payTokenQuotes();
|
|
11033
|
-
const target2 = targetToken();
|
|
11093
|
+
const target2 = store.targetToken();
|
|
11034
11094
|
const chains = chainMap();
|
|
11035
11095
|
if (tokens.length === 0 || !target2) return [];
|
|
11036
11096
|
const quoteMap = /* @__PURE__ */ new Map();
|
|
@@ -11110,13 +11170,81 @@ function ReceiveComponent(props) {
|
|
|
11110
11170
|
logoURI: q.token.logoURI
|
|
11111
11171
|
};
|
|
11112
11172
|
});
|
|
11173
|
+
const {
|
|
11174
|
+
trackingOrderId,
|
|
11175
|
+
trackingProviderName,
|
|
11176
|
+
trackingProviderIcon,
|
|
11177
|
+
trackingInputAmount,
|
|
11178
|
+
executionError,
|
|
11179
|
+
handleConfirm,
|
|
11180
|
+
handleRetry,
|
|
11181
|
+
handleNewSwap
|
|
11182
|
+
} = useReceiveExecution({
|
|
11183
|
+
client,
|
|
11184
|
+
walletAdapter: () => props.walletAdapter,
|
|
11185
|
+
callbacks: () => props.callbacks,
|
|
11186
|
+
apiEndpoint: () => props.config.apiEndpoint,
|
|
11187
|
+
recipient: store.recipient,
|
|
11188
|
+
needRecipient,
|
|
11189
|
+
walletAddress: walletAddress2,
|
|
11190
|
+
targetToken: store.targetToken,
|
|
11191
|
+
selectedPayToken,
|
|
11192
|
+
payTokenQuotes,
|
|
11193
|
+
setPayTokenQuotes,
|
|
11194
|
+
setLoadingQuotes,
|
|
11195
|
+
fetchSingleQuote,
|
|
11196
|
+
configAmount: () => props.config.amount,
|
|
11197
|
+
setExecPhase: store.setExecPhase,
|
|
11198
|
+
setFromToken: store.setFromToken,
|
|
11199
|
+
setError: store.setError,
|
|
11200
|
+
setErrorCode: store.setErrorCode,
|
|
11201
|
+
storeReset: store.reset,
|
|
11202
|
+
storeClearError: store.clearError,
|
|
11203
|
+
onRetry: () => {
|
|
11204
|
+
setSelectedPayToken(null);
|
|
11205
|
+
const tokens = balancePayTokens();
|
|
11206
|
+
if (tokens.length > 0) fetchPayTokenQuotes(tokens);
|
|
11207
|
+
},
|
|
11208
|
+
onReset: () => {
|
|
11209
|
+
setSelectedPayIndex(0);
|
|
11210
|
+
setSelectedPayToken(null);
|
|
11211
|
+
const tokens = balancePayTokens();
|
|
11212
|
+
if (tokens.length > 0) fetchPayTokenQuotes(tokens);
|
|
11213
|
+
}
|
|
11214
|
+
});
|
|
11215
|
+
useOrderTracking({
|
|
11216
|
+
client,
|
|
11217
|
+
walletAddress: walletAddress2,
|
|
11218
|
+
trackingOrderId,
|
|
11219
|
+
phase,
|
|
11220
|
+
execPhase: store.execPhase,
|
|
11221
|
+
setOrder: store.setOrder,
|
|
11222
|
+
setExecPhase: store.setExecPhase,
|
|
11223
|
+
onOrderFilled: (order) => {
|
|
11224
|
+
const selected2 = selectedPayToken();
|
|
11225
|
+
props.callbacks?.onSwapSuccess?.({
|
|
11226
|
+
orderId: order.id,
|
|
11227
|
+
fromToken: selected2?.symbol ?? "",
|
|
11228
|
+
toToken: store.targetToken()?.symbol ?? "",
|
|
11229
|
+
fromAmount: order.srcAmount,
|
|
11230
|
+
toAmount: order.destAmount,
|
|
11231
|
+
txHash: order.depositTxHash
|
|
11232
|
+
});
|
|
11233
|
+
},
|
|
11234
|
+
onOrderFailed: (order) => {
|
|
11235
|
+
props.callbacks?.onSwapError?.({
|
|
11236
|
+
code: ErrorCode.ORDER_FAILED,
|
|
11237
|
+
message: "Order " + order.status
|
|
11238
|
+
});
|
|
11239
|
+
}
|
|
11240
|
+
});
|
|
11113
11241
|
const refreshSinglePayTokenQuote = async (payToken) => {
|
|
11114
11242
|
const c = client();
|
|
11115
11243
|
const addr = walletAddress2();
|
|
11116
|
-
const target2 =
|
|
11244
|
+
const target2 = store.targetToken();
|
|
11117
11245
|
if (!c || !addr || !target2 || typeof target2.decimals !== "number") return;
|
|
11118
11246
|
const baseAmount = toBaseUnits(props.config.amount, target2.decimals);
|
|
11119
|
-
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2,
|
|
11247
|
+
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2, store.recipient());
|
|
11120
11248
|
if (quote2) {
|
|
11121
11249
|
const existing = payTokenQuotes();
|
|
11122
11250
|
const updated = [...existing];
|
|
@@ -11127,10 +11255,6 @@ function ReceiveComponent(props) {
|
|
|
11127
11255
|
updated.push(quote2);
|
|
11128
11256
|
}
|
|
11129
11257
|
setPayTokenQuotes(updated);
|
|
11130
|
-
if (sm.state().phase === "idle" || sm.state().phase === "quoting") {
|
|
11131
|
-
if (sm.state().phase === "idle") sm.transition("quoting");
|
|
11132
|
-
sm.transition("quoted");
|
|
11133
|
-
}
|
|
11134
11258
|
}
|
|
11135
11259
|
};
|
|
11136
11260
|
const handlePayTokenSelect = (index) => {
|
|
@@ -11143,24 +11267,12 @@ function ReceiveComponent(props) {
|
|
|
11143
11267
|
void refreshSinglePayTokenQuote(payToken);
|
|
11144
11268
|
}
|
|
11145
11269
|
};
|
|
11146
|
-
const handleConnect = async () => {
|
|
11147
|
-
if (!props.walletAdapter) {
|
|
11148
|
-
console.warn("[TokenFlight] No wallet adapter configured. Pass a walletAdapter to enable wallet connection.\nSee: https://embed.tokenflight.ai/guides/wallet-adapter/");
|
|
11149
|
-
props.callbacks?.onConnectWallet?.();
|
|
11150
|
-
return;
|
|
11151
|
-
}
|
|
11152
|
-
try {
|
|
11153
|
-
await props.walletAdapter.connect();
|
|
11154
|
-
} catch {
|
|
11155
|
-
sm.setError("Failed to connect wallet", ErrorCode.WALLET_CONNECTION_FAILED);
|
|
11156
|
-
}
|
|
11157
|
-
};
|
|
11158
11270
|
const handleTokenSelect = async (token) => {
|
|
11159
11271
|
setSelectorOpen(false);
|
|
11160
11272
|
setPayTokenSelectorOpen(false);
|
|
11161
11273
|
const c = client();
|
|
11162
11274
|
const addr = walletAddress2();
|
|
11163
|
-
const target2 =
|
|
11275
|
+
const target2 = store.targetToken();
|
|
11164
11276
|
if (!c || !addr || !target2 || typeof target2.decimals !== "number" || !token.address || typeof token.decimals !== "number") return;
|
|
11165
11277
|
setLoadingQuotes(true);
|
|
11166
11278
|
try {
|
|
@@ -11176,7 +11288,7 @@ function ReceiveComponent(props) {
|
|
|
11176
11288
|
balance: toBaseUnits(token.balance, token.decimals)
|
|
11177
11289
|
} : void 0
|
|
11178
11290
|
};
|
|
11179
|
-
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2,
|
|
11291
|
+
const quote2 = await fetchSingleQuote(c, payToken, baseAmount, addr, target2, store.recipient());
|
|
11180
11292
|
if (quote2) {
|
|
11181
11293
|
const existing = payTokenQuotes();
|
|
11182
11294
|
const idx = existing.findIndex((q) => q.token.address.toLowerCase() === token.address.toLowerCase() && q.token.chainId === token.chainId);
|
|
@@ -11193,165 +11305,12 @@ function ReceiveComponent(props) {
|
|
|
11193
11305
|
if (rankedIndex >= 0) {
|
|
11194
11306
|
setSelectedPayIndex(rankedIndex);
|
|
11195
11307
|
}
|
|
11196
|
-
if (sm.state().phase === "idle" || sm.state().phase === "quoting") {
|
|
11197
|
-
if (sm.state().phase === "idle") sm.transition("quoting");
|
|
11198
|
-
sm.transition("quoted");
|
|
11199
|
-
}
|
|
11200
11308
|
}
|
|
11201
11309
|
} catch {
|
|
11202
11310
|
} finally {
|
|
11203
11311
|
setLoadingQuotes(false);
|
|
11204
11312
|
}
|
|
11205
11313
|
};
|
|
11206
|
-
const handleConfirm = async () => {
|
|
11207
|
-
const selectedToken = selectedPayToken();
|
|
11208
|
-
const selected2 = selectedToken ? payTokenQuotes().find((quote2) => isSameToken(quote2.token, selectedToken)) : null;
|
|
11209
|
-
const addr = walletAddress2();
|
|
11210
|
-
if (!selected2 || !client() || !props.walletAdapter || !addr) return;
|
|
11211
|
-
if (needRecipient() && !sm.state().recipient) {
|
|
11212
|
-
sm.setError("Recipient address is required for cross-chain swaps", ErrorCode.INVALID_CONFIG);
|
|
11213
|
-
return;
|
|
11214
|
-
}
|
|
11215
|
-
const validBefore = selected2.route.quote.validBefore;
|
|
11216
|
-
if (validBefore && Date.now() / 1e3 > validBefore) {
|
|
11217
|
-
setLoadingQuotes(true);
|
|
11218
|
-
try {
|
|
11219
|
-
const target2 = sm.state().targetToken;
|
|
11220
|
-
if (!target2 || typeof target2.decimals !== "number") return;
|
|
11221
|
-
const baseAmount = toBaseUnits(props.config.amount, target2.decimals);
|
|
11222
|
-
const refreshed = await fetchSingleQuote(client(), selected2.token, baseAmount, addr, target2, sm.state().recipient);
|
|
11223
|
-
if (refreshed) {
|
|
11224
|
-
const updated = [...payTokenQuotes()];
|
|
11225
|
-
const existingIdx = updated.findIndex((quote2) => isSameToken(quote2.token, selected2.token));
|
|
11226
|
-
if (existingIdx >= 0) {
|
|
11227
|
-
updated[existingIdx] = refreshed;
|
|
11228
|
-
} else {
|
|
11229
|
-
updated.push(refreshed);
|
|
11230
|
-
}
|
|
11231
|
-
setPayTokenQuotes(updated);
|
|
11232
|
-
} else {
|
|
11233
|
-
sm.setError("Quote expired and could not be refreshed", ErrorCode.QUOTE_EXPIRED);
|
|
11234
|
-
return;
|
|
11235
|
-
}
|
|
11236
|
-
} catch {
|
|
11237
|
-
sm.setError("Quote expired and could not be refreshed", ErrorCode.QUOTE_EXPIRED);
|
|
11238
|
-
return;
|
|
11239
|
-
} finally {
|
|
11240
|
-
setLoadingQuotes(false);
|
|
11241
|
-
}
|
|
11242
|
-
}
|
|
11243
|
-
const confirmedToken = selectedPayToken();
|
|
11244
|
-
const confirmedQuote = confirmedToken ? payTokenQuotes().find((quote2) => isSameToken(quote2.token, confirmedToken)) : null;
|
|
11245
|
-
if (!confirmedQuote) return;
|
|
11246
|
-
sm.setFromToken({
|
|
11247
|
-
chainId: confirmedQuote.token.chainId,
|
|
11248
|
-
address: confirmedQuote.token.address,
|
|
11249
|
-
symbol: confirmedQuote.token.symbol,
|
|
11250
|
-
name: confirmedQuote.token.name,
|
|
11251
|
-
decimals: confirmedQuote.token.decimals,
|
|
11252
|
-
logoURI: confirmedQuote.token.logoURI
|
|
11253
|
-
});
|
|
11254
|
-
setTrackingProviderName(confirmedQuote.route.routeId ?? null);
|
|
11255
|
-
const apiBase2 = props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
|
|
11256
|
-
setTrackingProviderIcon(confirmedQuote.route.icon ? `${apiBase2}${confirmedQuote.route.icon}` : null);
|
|
11257
|
-
setTrackingInputAmount(toDisplayAmount(confirmedQuote.route.quote.amountIn, confirmedQuote.token.decimals));
|
|
11258
|
-
setExecutionError(null);
|
|
11259
|
-
sm.transition("building");
|
|
11260
|
-
try {
|
|
11261
|
-
const depositData = await client().buildDeposit({
|
|
11262
|
-
from: addr,
|
|
11263
|
-
quoteId: confirmedQuote.quoteId,
|
|
11264
|
-
routeId: confirmedQuote.route.routeId
|
|
11265
|
-
});
|
|
11266
|
-
sm.transition("awaiting-wallet");
|
|
11267
|
-
let txHash;
|
|
11268
|
-
if (depositData.kind === "CONTRACT_CALL" && depositData.approvals) {
|
|
11269
|
-
for (const approval of depositData.approvals) {
|
|
11270
|
-
if (approval.type === "eip1193_request") {
|
|
11271
|
-
const result = await props.walletAdapter.executeWalletAction({
|
|
11272
|
-
type: "eip1193_request",
|
|
11273
|
-
chainId: confirmedQuote.token.chainId,
|
|
11274
|
-
method: approval.request.method,
|
|
11275
|
-
params: approval.request.params
|
|
11276
|
-
});
|
|
11277
|
-
if (!result.success) {
|
|
11278
|
-
throw new TokenFlightError(ErrorCode.WALLET_ACTION_FAILED, result.error ?? "Wallet action failed");
|
|
11279
|
-
}
|
|
11280
|
-
if (approval.deposit) txHash = result.txHash ?? txHash;
|
|
11281
|
-
} else if (approval.type === "solana_sendTransaction") {
|
|
11282
|
-
const result = await props.walletAdapter.executeWalletAction({
|
|
11283
|
-
type: "solana_signAndSendTransaction",
|
|
11284
|
-
transaction: approval.transaction
|
|
11285
|
-
});
|
|
11286
|
-
if (!result.success) {
|
|
11287
|
-
throw new TokenFlightError(ErrorCode.WALLET_ACTION_FAILED, result.error ?? "Wallet action failed");
|
|
11288
|
-
}
|
|
11289
|
-
if (approval.deposit) txHash = result.txHash ?? txHash;
|
|
11290
|
-
}
|
|
11291
|
-
}
|
|
11292
|
-
}
|
|
11293
|
-
if (!txHash) {
|
|
11294
|
-
throw new TokenFlightError(ErrorCode.TRANSACTION_FAILED, "No deposit transaction hash received");
|
|
11295
|
-
}
|
|
11296
|
-
sm.transition("submitting");
|
|
11297
|
-
const submitResult = await client().submitDeposit({
|
|
11298
|
-
quoteId: confirmedQuote.quoteId,
|
|
11299
|
-
routeId: confirmedQuote.route.routeId,
|
|
11300
|
-
txHash
|
|
11301
|
-
});
|
|
11302
|
-
sm.transition("tracking");
|
|
11303
|
-
setTrackingOrderId(submitResult.orderId);
|
|
11304
|
-
} catch (err) {
|
|
11305
|
-
const errorMsg = err instanceof Error ? err.message : typeof err === "string" ? err : "Transaction failed";
|
|
11306
|
-
setExecutionError(errorMsg);
|
|
11307
|
-
if (err instanceof TokenFlightError) {
|
|
11308
|
-
props.callbacks?.onSwapError?.({
|
|
11309
|
-
code: err.code,
|
|
11310
|
-
message: err.message,
|
|
11311
|
-
details: err.details
|
|
11312
|
-
});
|
|
11313
|
-
} else {
|
|
11314
|
-
props.callbacks?.onSwapError?.({
|
|
11315
|
-
code: ErrorCode.TRANSACTION_FAILED,
|
|
11316
|
-
message: String(err)
|
|
11317
|
-
});
|
|
11318
|
-
}
|
|
11319
|
-
}
|
|
11320
|
-
};
|
|
11321
|
-
const handleRetry = () => {
|
|
11322
|
-
setExecutionError(null);
|
|
11323
|
-
setSelectedPayToken(null);
|
|
11324
|
-
sm.transition("idle");
|
|
11325
|
-
const tokens = balancePayTokens();
|
|
11326
|
-
if (tokens.length > 0) {
|
|
11327
|
-
fetchPayTokenQuotes(tokens);
|
|
11328
|
-
}
|
|
11329
|
-
};
|
|
11330
|
-
const handleNewSwap = () => {
|
|
11331
|
-
sm.clearRoutes();
|
|
11332
|
-
sm.setPaymentAmount("");
|
|
11333
|
-
sm.setFromToken(null);
|
|
11334
|
-
sm.setOrder(null);
|
|
11335
|
-
setSelectedPayIndex(0);
|
|
11336
|
-
setSelectedPayToken(null);
|
|
11337
|
-
setTrackingOrderId(null);
|
|
11338
|
-
setTrackingProviderName(null);
|
|
11339
|
-
setTrackingProviderIcon(null);
|
|
11340
|
-
setTrackingInputAmount(null);
|
|
11341
|
-
setExecutionError(null);
|
|
11342
|
-
setPayTokenQuotes([]);
|
|
11343
|
-
queryClient.removeQueries({
|
|
11344
|
-
queryKey: ["quote", client().baseUrl]
|
|
11345
|
-
});
|
|
11346
|
-
queryClient.removeQueries({
|
|
11347
|
-
queryKey: ["order", client().baseUrl]
|
|
11348
|
-
});
|
|
11349
|
-
sm.transition("idle");
|
|
11350
|
-
const tokens = balancePayTokens();
|
|
11351
|
-
if (tokens.length > 0) {
|
|
11352
|
-
fetchPayTokenQuotes(tokens);
|
|
11353
|
-
}
|
|
11354
|
-
};
|
|
11355
11314
|
const handleAccountClick = async () => {
|
|
11356
11315
|
if (props.walletAdapter?.openAccountModal) {
|
|
11357
11316
|
await props.walletAdapter.openAccountModal();
|
|
@@ -11360,13 +11319,8 @@ function ReceiveComponent(props) {
|
|
|
11360
11319
|
}
|
|
11361
11320
|
};
|
|
11362
11321
|
const truncateAddress = (addr) => `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
11363
|
-
const
|
|
11364
|
-
const
|
|
11365
|
-
const p = phase();
|
|
11366
|
-
return p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking";
|
|
11367
|
-
};
|
|
11368
|
-
const targetSymbol = () => state().targetToken?.symbol ?? "USDC";
|
|
11369
|
-
const targetAmount = () => state().targetAmount || props.config.amount;
|
|
11322
|
+
const targetSymbol = () => store.targetToken()?.symbol ?? "USDC";
|
|
11323
|
+
const targetAmount = () => store.targetAmount() || props.config.amount;
|
|
11370
11324
|
const titleText = createMemo(() => {
|
|
11371
11325
|
const raw = props.config.titleText?.trim();
|
|
11372
11326
|
return raw && raw.length > 0 ? raw : "TokenFlight";
|
|
@@ -11383,7 +11337,7 @@ function ReceiveComponent(props) {
|
|
|
11383
11337
|
var _el$ = _tmpl$3(), _el$2 = _el$.firstChild;
|
|
11384
11338
|
insert(_el$, createComponent(Show, {
|
|
11385
11339
|
get when() {
|
|
11386
|
-
return memo(() =>
|
|
11340
|
+
return memo(() => phase() === "success")() && store.order();
|
|
11387
11341
|
},
|
|
11388
11342
|
get fallback() {
|
|
11389
11343
|
return createComponent(Show, {
|
|
@@ -11516,19 +11470,19 @@ function ReceiveComponent(props) {
|
|
|
11516
11470
|
color: "#0052FF",
|
|
11517
11471
|
size: 32,
|
|
11518
11472
|
get logoURI() {
|
|
11519
|
-
return
|
|
11473
|
+
return store.targetToken()?.logoURI;
|
|
11520
11474
|
}
|
|
11521
11475
|
}), null);
|
|
11522
11476
|
insert(_el$16, createComponent(Show, {
|
|
11523
11477
|
get when() {
|
|
11524
|
-
return
|
|
11478
|
+
return store.targetToken()?.chainId;
|
|
11525
11479
|
},
|
|
11526
11480
|
get children() {
|
|
11527
11481
|
var _el$17 = _tmpl$2();
|
|
11528
11482
|
insert(_el$17, createComponent(ChainDot, {
|
|
11529
11483
|
size: 12,
|
|
11530
11484
|
get iconUrl() {
|
|
11531
|
-
return chainIconUrl(apiBase(),
|
|
11485
|
+
return chainIconUrl(apiBase(), store.targetToken().chainId);
|
|
11532
11486
|
}
|
|
11533
11487
|
}));
|
|
11534
11488
|
createRenderEffect(() => className(_el$17, styles.targetChainDot));
|
|
@@ -11631,7 +11585,7 @@ function ReceiveComponent(props) {
|
|
|
11631
11585
|
}
|
|
11632
11586
|
}), createComponent(Show, {
|
|
11633
11587
|
get when() {
|
|
11634
|
-
return memo(() => !!(selectedQuoteRoute() && selectedFromToken()))() &&
|
|
11588
|
+
return memo(() => !!(selectedQuoteRoute() && selectedFromToken()))() && store.targetToken();
|
|
11635
11589
|
},
|
|
11636
11590
|
get fallback() {
|
|
11637
11591
|
return createComponent(Show, {
|
|
@@ -11666,7 +11620,7 @@ function ReceiveComponent(props) {
|
|
|
11666
11620
|
return selectedFromToken();
|
|
11667
11621
|
},
|
|
11668
11622
|
get toToken() {
|
|
11669
|
-
return
|
|
11623
|
+
return store.targetToken();
|
|
11670
11624
|
},
|
|
11671
11625
|
inline: true,
|
|
11672
11626
|
countdownSeconds,
|
|
@@ -11680,7 +11634,7 @@ function ReceiveComponent(props) {
|
|
|
11680
11634
|
var _el$24 = _tmpl$1();
|
|
11681
11635
|
insert(_el$24, createComponent(ActionButton, {
|
|
11682
11636
|
get phase() {
|
|
11683
|
-
return
|
|
11637
|
+
return phase();
|
|
11684
11638
|
},
|
|
11685
11639
|
get isConnected() {
|
|
11686
11640
|
return isConnected();
|
|
@@ -11692,7 +11646,7 @@ function ReceiveComponent(props) {
|
|
|
11692
11646
|
onConfirm: handleConfirm,
|
|
11693
11647
|
onRetry: handleRetry,
|
|
11694
11648
|
get needsRecipient() {
|
|
11695
|
-
return memo(() => !!needRecipient())() && !
|
|
11649
|
+
return memo(() => !!needRecipient())() && !store.recipient();
|
|
11696
11650
|
},
|
|
11697
11651
|
onEnterRecipient: () => setRecipientEditorOpen(true),
|
|
11698
11652
|
get label() {
|
|
@@ -11709,13 +11663,13 @@ function ReceiveComponent(props) {
|
|
|
11709
11663
|
get children() {
|
|
11710
11664
|
return createComponent(OrderProgress, {
|
|
11711
11665
|
get order() {
|
|
11712
|
-
return
|
|
11666
|
+
return store.order();
|
|
11713
11667
|
},
|
|
11714
11668
|
get fromToken() {
|
|
11715
|
-
return
|
|
11669
|
+
return store.fromToken();
|
|
11716
11670
|
},
|
|
11717
11671
|
get toToken() {
|
|
11718
|
-
return
|
|
11672
|
+
return store.targetToken();
|
|
11719
11673
|
},
|
|
11720
11674
|
get providerName() {
|
|
11721
11675
|
return trackingProviderName();
|
|
@@ -11727,10 +11681,10 @@ function ReceiveComponent(props) {
|
|
|
11727
11681
|
return props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
|
|
11728
11682
|
},
|
|
11729
11683
|
get inputAmount() {
|
|
11730
|
-
return trackingInputAmount() ??
|
|
11684
|
+
return trackingInputAmount() ?? "";
|
|
11731
11685
|
},
|
|
11732
11686
|
get outputAmount() {
|
|
11733
|
-
return
|
|
11687
|
+
return store.targetAmount();
|
|
11734
11688
|
},
|
|
11735
11689
|
onNewSwap: handleNewSwap,
|
|
11736
11690
|
mode: "receive",
|
|
@@ -11751,13 +11705,13 @@ function ReceiveComponent(props) {
|
|
|
11751
11705
|
get children() {
|
|
11752
11706
|
return createComponent(TransactionComplete, {
|
|
11753
11707
|
get order() {
|
|
11754
|
-
return
|
|
11708
|
+
return store.order();
|
|
11755
11709
|
},
|
|
11756
11710
|
get fromToken() {
|
|
11757
|
-
return
|
|
11711
|
+
return store.fromToken();
|
|
11758
11712
|
},
|
|
11759
11713
|
get toToken() {
|
|
11760
|
-
return
|
|
11714
|
+
return store.targetToken();
|
|
11761
11715
|
},
|
|
11762
11716
|
onNewSwap: handleNewSwap,
|
|
11763
11717
|
get apiEndpoint() {
|
|
@@ -11807,16 +11761,16 @@ function ReceiveComponent(props) {
|
|
|
11807
11761
|
}), null);
|
|
11808
11762
|
insert(_el$, createComponent(Show, {
|
|
11809
11763
|
get when() {
|
|
11810
|
-
return memo(() => !!recipientEditorOpen())() &&
|
|
11764
|
+
return memo(() => !!recipientEditorOpen())() && store.targetToken();
|
|
11811
11765
|
},
|
|
11812
11766
|
get children() {
|
|
11813
11767
|
var _el$4 = _tmpl$2();
|
|
11814
11768
|
insert(_el$4, createComponent(RecipientEditor, {
|
|
11815
11769
|
get initialValue() {
|
|
11816
|
-
return
|
|
11770
|
+
return store.recipient() ?? "";
|
|
11817
11771
|
},
|
|
11818
11772
|
get chainType() {
|
|
11819
|
-
return getChainType(
|
|
11773
|
+
return getChainType(store.targetToken().chainId);
|
|
11820
11774
|
},
|
|
11821
11775
|
onConfirm: (addr) => {
|
|
11822
11776
|
handleRecipientChange(addr);
|
|
@@ -11854,8 +11808,8 @@ const css11 = ".tf-c63ac0{border-radius:50%;display:flex;align-items:center;just
|
|
|
11854
11808
|
const css12 = "@keyframes tf-80a677{to{transform:rotate(360deg)}}@keyframes tf-d97ff2{0%,to{opacity:1}50%{opacity:.4}}@keyframes tf-c3558b{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes tf-89a83e{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(6px)}}@keyframes tf-ca9155{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes tf-d2dbc4{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes tf-54b7e7{0%,to{border-color:var(--tf-primary)}50%{border-color:var(--tf-primary-light)}}@keyframes tf-194f18{to{transform:rotate(360deg)}}@keyframes tf-cdef4a{0%{transform:scale(.3);opacity:0}50%{transform:scale(1.05)}70%{transform:scale(.95)}to{transform:scale(1);opacity:1}}@keyframes tf-fd8795{0%{transform:translateY(0) rotate(0)}to{transform:translateY(-4px) rotate(8deg)}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:host{display:block;font-family:DM Sans,sans-serif;color:var(--tf-text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--tf-font-2xs: 10px;--tf-font-xs: 11px;--tf-font-sm: 12px;--tf-font-base: 13px;--tf-font-md: 14px;--tf-font-lg: 15px;--tf-font-xl: 16px;--tf-font-2xl: 17px;--tf-font-heading: 20px;--tf-font-amount: 28px;--tf-font-amount-lg: 24px;--tf-font-amount-sm: 22px}button:focus-visible,a:focus-visible{outline:2px solid var(--tf-primary);outline-offset:2px;border-radius:4px}";
|
|
11855
11809
|
const css13 = ".tf-1ac2ef{border-radius:6px;background:var(--tf-skeleton);animation:tf-90e981 1.5s infinite}.tf-68a980{position:absolute;inset:0;border-radius:20px;display:flex;align-items:flex-start;z-index:10;overflow:hidden;animation:tf-552c66 .2s ease both}.tf-e7b9c7{width:100%;max-width:400px;min-width:360px;border-radius:20px;overflow:hidden;background:var(--tf-bg);border:1px solid var(--tf-border);box-shadow:var(--tf-shadow-lg);font-family:DM Sans,sans-serif;color:var(--tf-text);position:relative;transition:background .25s ease,border-color .25s ease,box-shadow .25s ease}.tf-b4f391{background:transparent}.tf-118b57{border:none;box-shadow:none}.tf-118b57 .tf-07225e{display:none}.tf-07225e{height:2px;background:linear-gradient(90deg,transparent,var(--tf-primary),transparent);opacity:.6}.tf-d01dff{padding:16px 20px 20px;animation:tf-ed0355 .3s ease .1s both}.tf-5bb68c{padding:12px 20px 0}.tf-04e1e2{margin:12px 20px 0;padding:14px;background:var(--tf-primary-light);border-radius:10px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;height:131px;box-sizing:border-box;animation:tf-b61e63 .25s ease both}.tf-d01908{color:var(--tf-text-tertiary);opacity:.4}.tf-1cc72b{font-size:var(--tf-font-base);color:var(--tf-text-secondary)}.tf-480f1a{padding:0 20px 16px;text-align:center}.tf-480f1a a{font-size:var(--tf-font-base);color:var(--tf-primary);text-decoration:none;font-family:JetBrains Mono,monospace}.tf-bc7950{text-align:center;margin-top:8px;margin-bottom:10px}.tf-bc7950 a{font-size:var(--tf-font-sm);color:var(--tf-primary);text-decoration:none;font-family:JetBrains Mono,monospace}.tf-d9b7b4{display:inline-flex;align-items:center;gap:4px;background:var(--tf-surface);border:1px solid var(--tf-border);border-radius:6px;padding:2px 8px;cursor:pointer;font-size:var(--tf-font-sm);font-family:JetBrains Mono,monospace;color:var(--tf-text-secondary);transition:background .15s,border-color .15s}.tf-d9b7b4:hover{background:var(--tf-surface-hover)}.tf-d9b7b4 svg{opacity:.4;transition:opacity .15s}.tf-d9b7b4:hover svg{opacity:.7}.tf-9398ea{border-style:dashed;border-color:var(--tf-primary)}.tf-9398ea .tf-2d9323{color:var(--tf-primary);font-style:italic;font-family:DM Sans,sans-serif}.tf-4567e1{cursor:default;opacity:.8}.tf-4567e1:hover{background:var(--tf-surface)}.tf-58881e{color:var(--tf-text-tertiary);font-style:italic}";
|
|
11856
11810
|
const swapCss = [css0, css1$1, css1, css3, css4, css6, css7, css8, css9, css10, css11, css12, css13].join("\n");
|
|
11857
|
-
const css2 = "@keyframes tf-540423{to{transform:rotate(360deg)}}.tf-d61a98{padding:0 20px}.tf-4574e9{height:162px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--tf-border) transparent}.tf-4574e9::-webkit-scrollbar{width:4px}.tf-4574e9::-webkit-scrollbar-track{background:transparent}.tf-4574e9::-webkit-scrollbar-thumb{background:var(--tf-border);border-radius:2px}.tf-2f8db2{display:flex;align-items:center;justify-content:space-between;padding:9px 11px;border-radius:11px;margin-bottom:4px;cursor:pointer;border:1px solid var(--tf-border-light);background:transparent;width:100%;font-family:DM Sans,sans-serif;transition:background .15s ease,border-color .15s ease}.tf-aaf1d0{border-color:var(--tf-primary);outline:.5px solid var(--tf-primary);outline-offset:-1px;background:var(--tf-primary-light)}.tf-328e9e{opacity:.4;cursor:not-allowed}.tf-af2c71{cursor:default;pointer-events:none}.tf-d7d776{width:32px;height:32px;border-radius:50%}.tf-c3e864{display:flex;align-items:center;padding:
|
|
11858
|
-
const css5 = ".tf-9b71d6{padding:16px 20px 12px;display:flex;justify-content:space-between;align-items:center;gap:7px}.tf-4c9136{padding:0 20px 10px}.tf-febe61{font-size:var(--tf-font-sm);color:var(--tf-text-tertiary);font-weight:500;margin-bottom:6px;text-align:left}.tf-a27aab{display:flex;align-items:center;gap:10px;padding:
|
|
11811
|
+
const css2 = "@keyframes tf-540423{to{transform:rotate(360deg)}}.tf-d61a98{padding:0 20px}.tf-4574e9{height:162px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--tf-border) transparent}.tf-4574e9::-webkit-scrollbar{width:4px}.tf-4574e9::-webkit-scrollbar-track{background:transparent}.tf-4574e9::-webkit-scrollbar-thumb{background:var(--tf-border);border-radius:2px}.tf-2f8db2{display:flex;align-items:center;justify-content:space-between;padding:9px 11px;border-radius:11px;margin-bottom:4px;cursor:pointer;border:1px solid var(--tf-border-light);background:transparent;width:100%;font-family:DM Sans,sans-serif;transition:background .15s ease,border-color .15s ease}.tf-aaf1d0{border-color:var(--tf-primary);outline:.5px solid var(--tf-primary);outline-offset:-1px;background:var(--tf-primary-light)}.tf-328e9e{opacity:.4;cursor:not-allowed}.tf-af2c71{cursor:default;pointer-events:none}.tf-d7d776{width:32px;height:32px;border-radius:50%}.tf-c3e864{display:flex;align-items:center;padding:11px 14px;border-radius:12px;border:1px solid var(--tf-border-light);background:var(--tf-input-bg);cursor:default;pointer-events:none}.tf-44450a{display:flex;flex-direction:column;gap:6px}.tf-6c1e97{height:10px}.tf-2174f1{width:52px}.tf-2d3530{width:40px}.tf-2733a9{display:flex;flex-direction:column;align-items:flex-end;gap:6px}.tf-54150b{width:60px}.tf-7aabe1{width:44px}.tf-c41b7c{display:flex;align-items:center;gap:9px}.tf-142024{position:relative}.tf-3b42da{position:absolute;bottom:-1px;right:-1px;width:11px;height:11px;border-radius:50%;background:var(--tf-surface);border:1px solid var(--tf-border);display:flex;align-items:center;justify-content:center}.tf-b7faa4{text-align:left}.tf-1ae7a3{display:flex;align-items:center;gap:5px}.tf-b949b8{font-size:var(--tf-font-base);font-weight:600;color:var(--tf-text)}.tf-2f811b{font-size:var(--tf-font-2xs);font-weight:700;padding:1px 4px;border-radius:3px;background:var(--tf-success-bg);color:var(--tf-success);letter-spacing:.03em}.tf-6542b9{font-size:var(--tf-font-xs);color:var(--tf-text-tertiary)}.tf-e613ff{text-align:right}.tf-630df3{font-size:var(--tf-font-base);font-weight:600;font-family:JetBrains Mono,monospace;color:var(--tf-text)}.tf-0be2ff{font-size:var(--tf-font-xs);color:var(--tf-text-tertiary);font-family:JetBrains Mono,monospace}.tf-dad192{font-size:var(--tf-font-base);font-weight:600;font-family:JetBrains Mono,monospace;color:var(--tf-text)}.tf-840c29{font-size:var(--tf-font-xs);color:var(--tf-text-tertiary);font-family:JetBrains Mono,monospace}.tf-09818b{display:flex;align-items:center;padding:10px 14px;border-radius:12px;border:1px solid var(--tf-border-light);background:var(--tf-input-bg);cursor:pointer;width:100%;font-family:DM Sans,sans-serif;transition:background .15s ease,border-color .15s ease}.tf-09818b:hover{border-color:var(--tf-primary);background:var(--tf-primary-light)}.tf-c7ba0f{display:flex;align-items:center;gap:9px}.tf-dea0cb{text-align:left}.tf-41931a{display:flex;align-items:center;gap:5px}.tf-3d2f5a{margin-left:auto;text-align:right;margin-right:8px}.tf-9a379d{font-size:var(--tf-font-lg);font-weight:500;font-family:JetBrains Mono,monospace;color:var(--tf-text);letter-spacing:-.02em}.tf-c11354{font-size:var(--tf-font-xs);color:var(--tf-text-tertiary);font-family:JetBrains Mono,monospace}.tf-864468{color:var(--tf-text-tertiary);display:flex;align-items:center;flex-shrink:0;transition:transform .2s ease}.tf-8299cf{flex:1;overflow-y:auto;padding:0 8px 8px;scrollbar-width:thin;scrollbar-color:var(--tf-border) transparent}.tf-176d77{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-radius:12px;cursor:pointer;background:transparent;transition:background .1s;border:none;width:100%;font-family:DM Sans,sans-serif;color:var(--tf-text)}.tf-176d77:hover{background:var(--tf-surface-hover)}.tf-2df5d9{background:var(--tf-primary-light)}.tf-dc503e{opacity:.4;cursor:not-allowed}.tf-ebbc44{display:flex;align-items:center;gap:12px}.tf-5f455f{text-align:left}.tf-15ee78{display:flex;align-items:center;gap:6px}.tf-976d83{font-size:var(--tf-font-lg);font-weight:600;color:var(--tf-text)}.tf-ba2eec{font-size:var(--tf-font-sm);color:var(--tf-text-tertiary)}.tf-a37921{text-align:right}.tf-cf71b6{font-size:var(--tf-font-md);font-weight:600;font-family:JetBrains Mono,monospace;color:var(--tf-text)}.tf-7474a9{font-size:var(--tf-font-sm);color:var(--tf-text-tertiary);font-family:JetBrains Mono,monospace}.tf-772a9c{flex-shrink:0;padding:4px 8px 12px;border-top:1px solid var(--tf-border-light)}.tf-5fb6ad{display:flex;flex-direction:column;align-items:center;justify-content:center;height:197px;gap:8px;padding:16px 20px}.tf-86e8e0{flex-direction:row;gap:10px}.tf-66007c{color:var(--tf-text-tertiary);opacity:.5}.tf-73bbbc{width:24px;height:24px;display:flex;align-items:center;justify-content:center;opacity:.6;color:var(--tf-primary);animation:tf-540423 1s linear infinite}.tf-12c6bb{font-size:var(--tf-font-md);font-weight:600;color:var(--tf-text-secondary)}.tf-7a8fe0{font-size:var(--tf-font-sm);color:var(--tf-text-tertiary);text-align:center;line-height:1.4}.tf-22f94f{display:flex;align-items:center;justify-content:center;gap:4px;padding:4px 0 2px;font-size:var(--tf-font-sm);color:var(--tf-primary);cursor:pointer;font-weight:500;background:none;border:none;width:100%;font-family:DM Sans,sans-serif}";
|
|
11812
|
+
const css5 = ".tf-9b71d6{padding:16px 20px 12px;display:flex;justify-content:space-between;align-items:center;gap:7px}.tf-4c9136{padding:0 20px 10px}.tf-febe61{font-size:var(--tf-font-sm);color:var(--tf-text-tertiary);font-weight:500;margin-bottom:6px;text-align:left}.tf-a27aab{display:flex;align-items:center;gap:10px;padding:8px 14px;background:var(--tf-input-bg);border-radius:12px;border:1px solid var(--tf-border-light)}.tf-f0b3f5{position:relative;flex-shrink:0}.tf-7a6fbc{position:absolute;bottom:-1px;right:-1px;width:12px;height:12px}.tf-e9e9a1{font-size:var(--tf-font-amount-sm);font-weight:700;letter-spacing:-.02em}.tf-f3baad{font-size:var(--tf-font-lg);font-weight:500;color:var(--tf-text-secondary)}.tf-0131e4{margin-left:auto;font-size:var(--tf-font-sm);color:var(--tf-text-tertiary);font-family:JetBrains Mono,monospace}";
|
|
11859
11813
|
const receiveCss = [css0, css1, css2, css3, css4, css5, css6, css7, css8, css9, css10, css11, css12, css13].join("\n");
|
|
11860
11814
|
const lightVars = {
|
|
11861
11815
|
"--tf-bg": "#ffffff",
|
|
@@ -12439,14 +12393,14 @@ function parseBooleanProp(value2) {
|
|
|
12439
12393
|
}
|
|
12440
12394
|
return void 0;
|
|
12441
12395
|
}
|
|
12442
|
-
|
|
12443
|
-
|
|
12396
|
+
const [defaultWalletAdapter, setDefaultWalletAdapter] = createSignal();
|
|
12397
|
+
const [defaultCallbacks, setDefaultCallbacks] = createSignal();
|
|
12444
12398
|
function registerElements(options = {}) {
|
|
12445
12399
|
if ("walletAdapter" in options) {
|
|
12446
|
-
|
|
12400
|
+
setDefaultWalletAdapter(() => options.walletAdapter);
|
|
12447
12401
|
}
|
|
12448
12402
|
if ("callbacks" in options) {
|
|
12449
|
-
|
|
12403
|
+
setDefaultCallbacks(() => options.callbacks);
|
|
12450
12404
|
}
|
|
12451
12405
|
if (typeof customElements === "undefined") return;
|
|
12452
12406
|
if (!customElements.get("tokenflight-swap")) {
|
|
@@ -12496,11 +12450,6 @@ ${swapCss}`;
|
|
|
12496
12450
|
});
|
|
12497
12451
|
const elementWalletAdapter = element.__walletAdapter;
|
|
12498
12452
|
const elementCallbacks = element.__callbacks;
|
|
12499
|
-
const walletAdapter = elementWalletAdapter ?? defaultWalletAdapter;
|
|
12500
|
-
const callbacks = elementCallbacks ? {
|
|
12501
|
-
...defaultCallbacks,
|
|
12502
|
-
...elementCallbacks
|
|
12503
|
-
} : defaultCallbacks;
|
|
12504
12453
|
return [(() => {
|
|
12505
12454
|
var _el$ = _tmpl$();
|
|
12506
12455
|
setAttribute(_el$, "nonce", nonce);
|
|
@@ -12511,8 +12460,15 @@ ${swapCss}`;
|
|
|
12511
12460
|
get children() {
|
|
12512
12461
|
return createComponent(SwapComponent, {
|
|
12513
12462
|
config,
|
|
12514
|
-
walletAdapter
|
|
12515
|
-
|
|
12463
|
+
get walletAdapter() {
|
|
12464
|
+
return elementWalletAdapter ?? defaultWalletAdapter();
|
|
12465
|
+
},
|
|
12466
|
+
get callbacks() {
|
|
12467
|
+
return elementCallbacks ? {
|
|
12468
|
+
...defaultCallbacks(),
|
|
12469
|
+
...elementCallbacks
|
|
12470
|
+
} : defaultCallbacks();
|
|
12471
|
+
}
|
|
12516
12472
|
});
|
|
12517
12473
|
}
|
|
12518
12474
|
})];
|
|
@@ -12569,11 +12525,6 @@ ${receiveCss}`;
|
|
|
12569
12525
|
});
|
|
12570
12526
|
const elementWalletAdapter = element.__walletAdapter;
|
|
12571
12527
|
const elementCallbacks = element.__callbacks;
|
|
12572
|
-
const walletAdapter = elementWalletAdapter ?? defaultWalletAdapter;
|
|
12573
|
-
const callbacks = elementCallbacks ? {
|
|
12574
|
-
...defaultCallbacks,
|
|
12575
|
-
...elementCallbacks
|
|
12576
|
-
} : defaultCallbacks;
|
|
12577
12528
|
return [(() => {
|
|
12578
12529
|
var _el$2 = _tmpl$();
|
|
12579
12530
|
setAttribute(_el$2, "nonce", nonce);
|
|
@@ -12584,8 +12535,15 @@ ${receiveCss}`;
|
|
|
12584
12535
|
get children() {
|
|
12585
12536
|
return createComponent(ReceiveComponent, {
|
|
12586
12537
|
config,
|
|
12587
|
-
walletAdapter
|
|
12588
|
-
|
|
12538
|
+
get walletAdapter() {
|
|
12539
|
+
return elementWalletAdapter ?? defaultWalletAdapter();
|
|
12540
|
+
},
|
|
12541
|
+
get callbacks() {
|
|
12542
|
+
return elementCallbacks ? {
|
|
12543
|
+
...defaultCallbacks(),
|
|
12544
|
+
...elementCallbacks
|
|
12545
|
+
} : defaultCallbacks();
|
|
12546
|
+
}
|
|
12589
12547
|
});
|
|
12590
12548
|
}
|
|
12591
12549
|
})];
|