@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.
@@ -8364,267 +8364,135 @@ function RecipientEditor(props) {
8364
8364
  return _el$;
8365
8365
  })();
8366
8366
  }
8367
- const VALID_TRANSITIONS = {
8368
- idle: ["quoting", "quoted", "error"],
8369
- quoting: ["quoted", "error", "idle"],
8370
- quoted: ["building", "quoting", "idle", "error"],
8371
- building: ["awaiting-wallet", "error", "quoted"],
8372
- "awaiting-wallet": ["submitting", "error", "quoted"],
8373
- submitting: ["tracking", "error", "quoted"],
8374
- tracking: ["success", "error"],
8375
- success: ["idle", "error"],
8376
- error: ["idle", "quoting", "quoted"]
8377
- };
8378
- function createSwapStateMachine() {
8379
- const [state, setState] = createSignal({
8380
- phase: "idle",
8381
- fromToken: null,
8382
- toToken: null,
8383
- inputAmount: "",
8384
- outputAmount: "",
8385
- routes: [],
8386
- quoteId: null,
8387
- selectedRouteId: null,
8388
- order: null,
8389
- walletAddress: null,
8390
- isStreaming: false,
8391
- error: null,
8392
- errorCode: null,
8393
- recipient: null
8394
- });
8395
- function transition(nextPhase) {
8396
- const current = state().phase;
8397
- const allowed = VALID_TRANSITIONS[current];
8398
- if (!allowed?.includes(nextPhase)) {
8399
- console.warn(
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
- setState((prev) => ({
8422
- ...prev,
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
- setState((prev) => ({
8473
- ...prev,
8474
- phase: "idle",
8475
- inputAmount: "",
8476
- outputAmount: "",
8477
- routes: [],
8478
- quoteId: null,
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
- state,
8488
- transition,
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
- setOutputAmount,
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
- setRecipient,
8434
+ setErrorCode,
8435
+ // Batch helpers
8436
+ clearError,
8502
8437
  reset
8503
8438
  };
8504
8439
  }
8505
- function createReceiveStateMachine() {
8506
- const [state, setState] = createSignal({
8507
- phase: "idle",
8508
- targetToken: null,
8509
- fromToken: null,
8510
- targetAmount: "",
8511
- paymentAmount: "",
8512
- routes: [],
8513
- quoteId: null,
8514
- selectedRouteId: null,
8515
- order: null,
8516
- walletAddress: null,
8517
- isStreaming: false,
8518
- error: null,
8519
- errorCode: null,
8520
- recipient: null
8521
- });
8522
- function transition(nextPhase) {
8523
- const current = state().phase;
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
- setState((prev) => ({
8549
- ...prev,
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
- setState((prev) => ({
8600
- ...prev,
8601
- phase: "idle",
8602
- routes: [],
8603
- quoteId: null,
8604
- selectedRouteId: null,
8605
- order: null,
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
- state,
8614
- transition,
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
- setPaymentAmount,
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 sm = createSwapStateMachine();
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 [noRoutes, setNoRoutes] = createSignal(false);
8892
- const [trackingProviderName, setTrackingProviderName] = createSignal(null);
8893
- const [trackingProviderIcon, setTrackingProviderIcon] = createSignal(null);
8894
- const [executionError, setExecutionError] = createSignal(null);
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 inputFiatText = createMemo(() => {
8961
- const amount2 = Number(inputAmount());
8962
- const price = fromUnitPriceUsd();
8963
- if (!Number.isFinite(amount2) || amount2 <= 0 || price === null) return null;
8964
- return t("swap.fiatValue", {
8965
- value: formatUsd(amount2 * price)
8966
- });
8967
- });
8968
- const outputFiatText = createMemo(() => {
8969
- const amount2 = Number(outputAmount() || "0");
8970
- const price = toUnitPriceUsd();
8971
- const p = phase();
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
- const hasRequest = !!quoteRequest();
9150
- return hasRequest && (p === "idle" || p === "quoting" || p === "quoted");
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
- const phase2 = sm.state().phase;
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
- sm.setError(error2.message, error2.code);
9299
+ store.setError(error2.message);
9300
+ store.setErrorCode(error2.code);
9180
9301
  } else {
9181
- sm.setError(String(error2));
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 (sm.state().phase === "error") {
9236
- sm.transition("idle");
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 handleConnect = async () => {
9254
- if (!props.walletAdapter) {
9255
- console.warn("[TokenFlight] No wallet adapter configured. Pass a walletAdapter to enable wallet connection.\nSee: https://embed.tokenflight.ai/guides/wallet-adapter/");
9256
- props.callbacks?.onConnectWallet?.();
9257
- return;
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
- if (!isAddressForChainType(addr, fromChainType)) {
9280
- sm.setError(t("error.walletChainMismatch"), ErrorCode.INVALID_CONFIG);
9281
- return;
9316
+ });
9317
+ onMount(() => {
9318
+ if (props.config.locale) {
9319
+ setLocale(props.config.locale);
9282
9320
  }
9283
- setTrackingProviderName(selectedRoute.routeId ?? null);
9284
- const apiBase = props.config.apiEndpoint ?? DEFAULT_API_ENDPOINT;
9285
- setTrackingProviderIcon(selectedRoute.icon ? `${apiBase}${selectedRoute.icon}` : null);
9286
- setExecutionError(null);
9287
- sm.transition("building");
9288
- try {
9289
- const depositData = await client().buildDeposit({
9290
- from: walletAddress2(),
9291
- quoteId: state2.quoteId,
9292
- routeId: selectedRoute.routeId
9293
- });
9294
- sm.transition("awaiting-wallet");
9295
- let txHash;
9296
- let signedTransaction;
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
- if (!txHash && !signedTransaction) {
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: err.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
- } else {
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.TRANSACTION_FAILED,
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
- const handleRetry = () => {
9359
- setExecutionError(null);
9360
- sm.transition("quoted");
9361
- };
9362
- const handleNewSwap = () => {
9363
- sm.clearRoutes();
9364
- sm.setOutputAmount("");
9365
- sm.setInputAmount("");
9366
- sm.setOrder(null);
9367
- setDebouncedAmountImmediate("");
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
- sm.transition("idle");
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
- sm.setFromToken(resolved);
9385
+ store.setFromToken(resolved);
9392
9386
  } else {
9393
- sm.setToToken(resolved);
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
- const current = sm.state();
9407
- const phase2 = current.phase;
9408
- const isBusy = phase2 === "building" || phase2 === "awaiting-wallet" || phase2 === "submitting" || phase2 === "tracking";
9409
- if (isBusy || !current.fromToken || !current.toToken) return;
9410
- sm.setFromToken(current.toToken);
9411
- sm.setToToken(current.fromToken);
9412
- sm.clearRoutes();
9413
- sm.setOutputAmount("");
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 bal = fromBalance();
9426
- if (bal && bal !== "0") {
9427
- handleAmountChange(bal);
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 showQuote = () => {
9439
- const p = phase();
9440
- return p === "quoted" || p === "building" || p === "awaiting-wallet" || p === "submitting" || p === "tracking" || p === "success";
9441
- };
9442
- const isExecuting = () => {
9443
- const p = phase();
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(() => state().phase === "success")() && state().order;
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 state().inputAmount;
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 state().fromToken;
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 state().fromToken.symbol ?? "?";
9596
+ return store.fromToken().symbol ?? "?";
9637
9597
  },
9638
9598
  color: "#2775CA",
9639
9599
  size: 24,
9640
9600
  get logoURI() {
9641
- return state().fromToken.logoURI;
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, state().fromToken.chainId);
9607
+ return chainIconUrl(client().baseUrl, store.fromToken().chainId);
9648
9608
  }
9649
9609
  }));
9650
- insert(_el$21, () => state().fromToken.symbol);
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())() && state().toToken;
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() || state().phase === "quoting"))() ? state().outputAmount || "0" : "0";
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() && state().phase !== "quoting" ? amountStyles.muted : ""}`));
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 state().toToken;
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 state().toToken.symbol ?? "?";
9754
+ return store.toToken().symbol ?? "?";
9795
9755
  },
9796
9756
  color: "#0052FF",
9797
9757
  size: 24,
9798
9758
  get logoURI() {
9799
- return state().toToken.logoURI;
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, state().toToken.chainId);
9765
+ return chainIconUrl(client().baseUrl, store.toToken().chainId);
9806
9766
  }
9807
9767
  }));
9808
- insert(_el$38, () => state().toToken.symbol);
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() && state().fromToken))() && state().toToken;
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 state().fromToken;
9829
+ return store.fromToken();
9870
9830
  },
9871
9831
  get toToken() {
9872
- return state().toToken;
9832
+ return store.toToken();
9873
9833
  },
9874
9834
  inline: true,
9875
9835
  countdownSeconds,
9876
9836
  countdownTotal: QUOTE_REFRESH_SECONDS,
9877
- showCountdown: () => state().phase === "quoted"
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 state().phase;
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 state().error ?? void 0;
9878
+ return store.error() ?? void 0;
9919
9879
  },
9920
9880
  get needsRecipient() {
9921
- return memo(() => !!needRecipient())() && !state().recipient;
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 state().order;
9895
+ return store.order();
9936
9896
  },
9937
9897
  get fromToken() {
9938
- return state().fromToken;
9898
+ return store.fromToken();
9939
9899
  },
9940
9900
  get toToken() {
9941
- return state().toToken;
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 state().inputAmount;
9913
+ return store.inputAmount();
9954
9914
  },
9955
9915
  get outputAmount() {
9956
- return state().outputAmount;
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 state().order;
9937
+ return store.order();
9978
9938
  },
9979
9939
  get fromToken() {
9980
- return state().fromToken;
9940
+ return store.fromToken();
9981
9941
  },
9982
9942
  get toToken() {
9983
- return state().toToken;
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())() && state().toToken;
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 state().recipient ?? "";
10001
+ return store.recipient() ?? "";
10042
10002
  },
10043
10003
  get chainType() {
10044
- return getChainType(state().toToken.chainId);
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
- candidates.sort((a, b) => {
10638
- if (a.tier !== b.tier) return a.tier - b.tier;
10639
- return a.gasCostScore - b.gasCostScore;
10640
- });
10641
- return candidates.map((c) => c.token);
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.toLowerCase() === b.address.toLowerCase();
10820
+ return a.chainId === b.chainId && normalizeTokenAddress(a.address) === normalizeTokenAddress(b.address);
10666
10821
  }
10667
10822
  function ReceiveComponent(props) {
10668
- const sm = createReceiveStateMachine();
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 targetToken = createMemo(() => sm.state().targetToken);
10690
- const phase = createMemo(() => sm.state().phase);
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 needRecipient = createMemo(() => {
10695
- const target2 = targetToken();
10696
- const from = selectedPayToken();
10697
- if (!target2 || !from || !isConnected()) return false;
10698
- return isCrossChainSwap(from.chainId, target2.chainId);
10699
- });
10700
- const recipientDisplay = createMemo(() => {
10701
- const r = recipientR();
10702
- if (r) return r;
10703
- if (isConnected() && walletAddress2() && !needRecipient()) return walletAddress2();
10704
- return null;
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
- sm.setRecipient(props.config.recipient);
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
- sm.setError("Invalid amount: must be greater than zero", ErrorCode.INVALID_AMOUNT);
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
- sm.setError("Failed to resolve target token metadata", ErrorCode.INVALID_CONFIG);
10900
+ store.setError("Failed to resolve target token metadata");
10901
+ store.setErrorCode(ErrorCode.INVALID_CONFIG);
10779
10902
  return;
10780
10903
  }
10781
- sm.setTargetToken(resolved);
10782
- sm.setTargetAmount(props.config.amount);
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
- sm.setError(err instanceof Error ? err.message : "Failed to resolve target token", ErrorCode.INVALID_CONFIG);
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 = sm.state().phase;
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 = sm.state().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 [countdownSeconds, setCountdownSeconds] = createSignal(QUOTE_REFRESH_SECONDS);
10929
- createEffect(() => {
10930
- if (phase() !== "quoted") {
10931
- setCountdownSeconds(QUOTE_REFRESH_SECONDS);
10932
- return;
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.ensureQueryData({
11026
+ const quoteResp = await queryClient.fetchQuery({
10961
11027
  queryKey: ["quote", c.baseUrl, request],
10962
- queryFn: () => c.getQuotes(request),
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 = sm.state().targetToken;
11053
+ const target2 = store.targetToken();
10986
11054
  if (!c || !addr || !target2 || typeof target2.decimals !== "number" || tokensToQuote.length === 0) return;
10987
- const phase2 = sm.state().phase;
10988
- if (phase2 === "idle" || phase2 === "quoted" || phase2 === "error") {
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, sm.state().recipient);
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 = sm.state().targetToken;
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, sm.state().recipient);
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 = sm.state().targetToken;
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, sm.state().recipient);
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 state = sm.state;
11364
- const isExecuting = () => {
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(() => state().phase === "success")() && state().order;
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 state().targetToken?.logoURI;
11473
+ return store.targetToken()?.logoURI;
11520
11474
  }
11521
11475
  }), null);
11522
11476
  insert(_el$16, createComponent(Show, {
11523
11477
  get when() {
11524
- return state().targetToken?.chainId;
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(), state().targetToken.chainId);
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()))() && state().targetToken;
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 state().targetToken;
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 state().phase;
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())() && !sm.state().recipient;
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 state().order;
11666
+ return store.order();
11713
11667
  },
11714
11668
  get fromToken() {
11715
- return state().fromToken;
11669
+ return store.fromToken();
11716
11670
  },
11717
11671
  get toToken() {
11718
- return state().targetToken;
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() ?? state().paymentAmount;
11684
+ return trackingInputAmount() ?? "";
11731
11685
  },
11732
11686
  get outputAmount() {
11733
- return state().targetAmount;
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 state().order;
11708
+ return store.order();
11755
11709
  },
11756
11710
  get fromToken() {
11757
- return state().fromToken;
11711
+ return store.fromToken();
11758
11712
  },
11759
11713
  get toToken() {
11760
- return state().targetToken;
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())() && sm.state().targetToken;
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 sm.state().recipient ?? "";
11770
+ return store.recipient() ?? "";
11817
11771
  },
11818
11772
  get chainType() {
11819
- return getChainType(sm.state().targetToken.chainId);
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:10px 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}";
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:10px 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}";
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
- let defaultWalletAdapter;
12443
- let defaultCallbacks;
12396
+ const [defaultWalletAdapter, setDefaultWalletAdapter] = createSignal();
12397
+ const [defaultCallbacks, setDefaultCallbacks] = createSignal();
12444
12398
  function registerElements(options = {}) {
12445
12399
  if ("walletAdapter" in options) {
12446
- defaultWalletAdapter = options.walletAdapter;
12400
+ setDefaultWalletAdapter(() => options.walletAdapter);
12447
12401
  }
12448
12402
  if ("callbacks" in options) {
12449
- defaultCallbacks = options.callbacks;
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
- callbacks
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
- callbacks
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
  })];