0xtrails 0.9.2 → 0.9.4

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.
Files changed (79) hide show
  1. package/dist/{ccip-g6lDdnrD.js → ccip-lAtzqne5.js} +1 -1
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/constants.d.ts +1 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/error.d.ts.map +1 -1
  7. package/dist/{index-D-QngA_s.js → index-D5AG6huo.js} +22290 -21786
  8. package/dist/index.js +3 -3
  9. package/dist/intents.d.ts +1 -1
  10. package/dist/intents.d.ts.map +1 -1
  11. package/dist/mutations.d.ts +5 -2
  12. package/dist/mutations.d.ts.map +1 -1
  13. package/dist/tokens.d.ts.map +1 -1
  14. package/dist/transactionIntent/constants.d.ts +1 -0
  15. package/dist/transactionIntent/constants.d.ts.map +1 -1
  16. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -1
  17. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  18. package/dist/transactionIntent/deposits/standardDeposit.d.ts +4 -1
  19. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  20. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
  21. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
  22. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  23. package/dist/transactionIntent/types.d.ts +2 -0
  24. package/dist/transactionIntent/types.d.ts.map +1 -1
  25. package/dist/transactionIntent/utils/resilientDepositTracker.d.ts +25 -0
  26. package/dist/transactionIntent/utils/resilientDepositTracker.d.ts.map +1 -0
  27. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  28. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  29. package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
  30. package/dist/widget/components/DynamicInputStyles.d.ts +2 -2
  31. package/dist/widget/components/Earn.d.ts.map +1 -1
  32. package/dist/widget/components/EarnPools.d.ts.map +1 -1
  33. package/dist/widget/components/Fund.d.ts.map +1 -1
  34. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  35. package/dist/widget/components/Receipt.d.ts.map +1 -1
  36. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  37. package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
  38. package/dist/widget/components/UserPreferences.d.ts.map +1 -1
  39. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  40. package/dist/widget/css/compiled.css +1 -1
  41. package/dist/widget/hooks/useQuote.d.ts +2 -0
  42. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  43. package/dist/widget/index.js +1 -1
  44. package/dist/widget/providers/TrailsProvider.d.ts +2 -0
  45. package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
  46. package/dist/widget/widget.d.ts +1 -0
  47. package/dist/widget/widget.d.ts.map +1 -1
  48. package/package.json +2 -2
  49. package/src/config.ts +1 -0
  50. package/src/constants.ts +1 -0
  51. package/src/error.ts +6 -1
  52. package/src/intents.ts +22 -1
  53. package/src/prices.ts +1 -1
  54. package/src/tokens.ts +4 -3
  55. package/src/transactionIntent/constants.ts +2 -0
  56. package/src/transactionIntent/deposits/depositOrchestrator.ts +7 -0
  57. package/src/transactionIntent/deposits/standardDeposit.ts +194 -37
  58. package/src/transactionIntent/handlers/crossChain.ts +152 -105
  59. package/src/transactionIntent/handlers/sameChainSameToken.ts +1 -0
  60. package/src/transactionIntent/quote/normalizeQuote.ts +7 -4
  61. package/src/transactionIntent/types.ts +2 -0
  62. package/src/transactionIntent/utils/resilientDepositTracker.ts +281 -0
  63. package/src/widget/compiled.css +1 -1
  64. package/src/widget/components/AccountIntentTransactionHistory.tsx +170 -87
  65. package/src/widget/components/ClassicSwap.tsx +7 -1
  66. package/src/widget/components/ConfigDisplay.tsx +5 -0
  67. package/src/widget/components/Earn.tsx +14 -1
  68. package/src/widget/components/EarnPools.tsx +180 -59
  69. package/src/widget/components/Fund.tsx +3 -1
  70. package/src/widget/components/PoolWithdraw.tsx +1 -1
  71. package/src/widget/components/QuoteDetails.tsx +12 -35
  72. package/src/widget/components/Receipt.tsx +66 -40
  73. package/src/widget/components/SlippageToleranceSettings.tsx +86 -44
  74. package/src/widget/components/TransactionDetails.tsx +138 -218
  75. package/src/widget/components/UserPreferences.tsx +114 -41
  76. package/src/widget/components/WalletConnect.tsx +111 -48
  77. package/src/widget/hooks/useQuote.ts +389 -352
  78. package/src/widget/providers/TrailsProvider.tsx +5 -0
  79. package/src/widget/widget.tsx +2 -0
@@ -1,25 +1,25 @@
1
- import React, { useState, useRef, useMemo, useEffect } from "react"
2
- import { useIntentTransactionHistory } from "../hooks/useIntentTransactionHistory.js"
3
- import type { IntentTransaction } from "../../transactions.js"
4
- import { TokenImage } from "./TokenImage.js"
5
- import { ScreenHeader } from "./ScreenHeader.js"
6
- import { TransactionDetails } from "./TransactionDetails.js"
7
- import { formatRawAmount } from "../../tokenBalances.js"
8
- import { formatRelativeDate } from "../../time.js"
9
- import { SearchInputField } from "./SearchInputField.js"
10
- import { Identicon } from "./Identicon.js"
11
- import { truncateAddress } from "../../utils.js"
12
- import { useConnections, useAccount, useWalletClient } from "wagmi"
1
+ import React, { useEffect, useMemo, useRef, useState } from "react"
2
+ import type { Intent } from "@0xtrails/api"
13
3
  import { ChevronDown, Info } from "lucide-react"
4
+ import { useAccount, useConnections, useWalletClient } from "wagmi"
14
5
  import { getExplorerUrl } from "../../explorer.js"
15
- import { ErrorDisplay } from "./ErrorDisplay.js"
16
6
  import { logger } from "../../logger.js"
17
- import { useIntentRecover } from "../../recover.js"
18
- import { useGetIntent } from "../hooks/useGetIntent.js"
19
7
  import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
20
- import type { Intent } from "@0xtrails/api"
21
- import { useTokenInfo, useGetTokenImageUrl } from "../../tokens.js"
22
8
  import { getQueryParam } from "../../queryParams.js"
9
+ import { useIntentRecover } from "../../recover.js"
10
+ import { formatRelativeDate } from "../../time.js"
11
+ import { formatRawAmount } from "../../tokenBalances.js"
12
+ import { useGetTokenImageUrl, useTokenInfo } from "../../tokens.js"
13
+ import type { IntentTransaction } from "../../transactions.js"
14
+ import { truncateAddress } from "../../utils.js"
15
+ import { useGetIntent } from "../hooks/useGetIntent.js"
16
+ import { useIntentTransactionHistory } from "../hooks/useIntentTransactionHistory.js"
17
+ import { ErrorDisplay } from "./ErrorDisplay.js"
18
+ import { Identicon } from "./Identicon.js"
19
+ import { ScreenHeader } from "./ScreenHeader.js"
20
+ import { SearchInputField } from "./SearchInputField.js"
21
+ import { TokenImage } from "./TokenImage.js"
22
+ import { TransactionDetails } from "./TransactionDetails.js"
23
23
 
24
24
  interface AccountIntentTransactionHistoryProps {
25
25
  accountAddress?: string
@@ -64,7 +64,7 @@ const ExecutionStatusBadge: React.FC<{ status?: string }> = ({ status }) => {
64
64
 
65
65
  return (
66
66
  <span
67
- className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(
67
+ className={`inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium ${getStatusColor(
68
68
  status,
69
69
  )}`}
70
70
  >
@@ -82,7 +82,7 @@ const TransactionItem: React.FC<{
82
82
  onCommitSuccess?: () => void
83
83
  }> = ({
84
84
  transaction,
85
- index,
85
+ index: _index,
86
86
  onRefetch,
87
87
  fetchedIntent,
88
88
  commitIntentMutation,
@@ -464,17 +464,13 @@ const TransactionItem: React.FC<{
464
464
  }, [refundTxHash, transaction.originChainId])
465
465
 
466
466
  return (
467
- <div className="border border-gray-200 dark:border-gray-700 rounded-lg p-3 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
468
- {/* Header with status and metadata */}
467
+ <div className="border border-gray-200 dark:border-gray-700 rounded-lg p-2 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
468
+ {/* Header with metadata */}
469
469
  <div className="flex items-center justify-between mb-2">
470
470
  <div className="flex items-center gap-2 flex-wrap">
471
- <span className="text-xs font-medium text-gray-600 dark:text-gray-400">
472
- #{index + 1}
473
- </span>
474
- <ExecutionStatusBadge status={transaction.executionStatus} />
475
471
  {dateInfo.relative && (
476
472
  <span
477
- className="text-xs text-gray-500 dark:text-gray-400 cursor-help"
473
+ className="text-xs text-gray-900 dark:text-gray-100 cursor-help"
478
474
  title={dateInfo.full || undefined}
479
475
  >
480
476
  {dateInfo.relative}
@@ -486,9 +482,24 @@ const TransactionItem: React.FC<{
486
482
  href={explorerUrl}
487
483
  target="_blank"
488
484
  rel="noopener noreferrer"
489
- className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 text-xs"
485
+ className="inline-flex items-center gap-1 text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 text-xs whitespace-nowrap"
486
+ title="View transaction on block explorer"
490
487
  >
491
- View on Explorer
488
+ <span>View on Explorer</span>
489
+ <svg
490
+ className="w-3 h-3 flex-shrink-0"
491
+ fill="none"
492
+ viewBox="0 0 24 24"
493
+ stroke="currentColor"
494
+ >
495
+ <title>External Link</title>
496
+ <path
497
+ strokeLinecap="round"
498
+ strokeLinejoin="round"
499
+ strokeWidth={2}
500
+ d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
501
+ />
502
+ </svg>
492
503
  </a>
493
504
  )}
494
505
  </div>
@@ -497,56 +508,83 @@ const TransactionItem: React.FC<{
497
508
  <div className="flex items-center justify-center mb-2">
498
509
  {/* Show token information if available, otherwise show intent addresses */}
499
510
  {transaction.originToken && transaction.destinationToken ? (
500
- <div className="flex items-center gap-2">
501
- {/* Origin Token with Chain */}
502
- <div className="flex items-center gap-1">
511
+ <div className="flex items-center justify-between w-full gap-3">
512
+ {/* Origin Token - Image on left, details on right */}
513
+ <div className="flex items-start gap-2 flex-1 max-w-[130px]">
503
514
  <TokenImage
504
515
  symbol={transaction.originToken.symbol}
505
516
  imageUrl={transaction.originToken.imageUrl}
506
517
  chainId={transaction.originToken.chainId}
507
- size={20}
518
+ size={28}
508
519
  />
509
- <span className="text-xs font-medium text-gray-900 dark:text-gray-100">
510
- {formatRawAmount(
511
- transaction.originTokenAmount || "0",
512
- transaction.originToken.decimals,
513
- )}{" "}
514
- {transaction.originToken.symbol}
515
- </span>
520
+ <div className="flex flex-col gap-0.5">
521
+ <span
522
+ className="text-xs font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap overflow-hidden text-ellipsis"
523
+ style={{ maxWidth: "85px" }}
524
+ >
525
+ {formatRawAmount(
526
+ transaction.originTokenAmount || "0",
527
+ transaction.originToken.decimals,
528
+ )}{" "}
529
+ {transaction.originToken.symbol}
530
+ </span>
531
+ {transaction.mainSigner && (
532
+ <div className="flex items-center gap-1 whitespace-nowrap">
533
+ <Identicon value={transaction.mainSigner} size={12} />
534
+ <span
535
+ className="text-xs"
536
+ style={{ color: "#71717A" }}
537
+ title={transaction.mainSigner}
538
+ >
539
+ {truncateAddress(transaction.mainSigner)}
540
+ </span>
541
+ </div>
542
+ )}
543
+ </div>
516
544
  </div>
517
545
 
518
546
  {/* Arrow */}
519
547
  <div className="flex items-center">
520
- <svg
521
- className="w-3 h-3 text-gray-400"
522
- fill="none"
523
- stroke="currentColor"
524
- viewBox="0 0 24 24"
525
- >
526
- <path
527
- strokeLinecap="round"
528
- strokeLinejoin="round"
529
- strokeWidth={2}
530
- d="M9 5l7 7-7 7"
531
- />
532
- </svg>
548
+ <span className="text-xl text-gray-400 dark:text-gray-500">
549
+
550
+ </span>
533
551
  </div>
534
552
 
535
- {/* Destination Token with Chain */}
536
- <div className="flex items-center gap-1">
553
+ {/* Destination Token - Image on left, details on right */}
554
+ <div className="flex items-start gap-2 flex-1 max-w-[130px]">
537
555
  <TokenImage
538
556
  symbol={transaction.destinationToken.symbol}
539
557
  imageUrl={transaction.destinationToken.imageUrl}
540
558
  chainId={transaction.destinationToken.chainId}
541
- size={20}
559
+ size={28}
542
560
  />
543
- <span className="text-xs font-medium text-gray-900 dark:text-gray-100">
544
- {formatRawAmount(
545
- transaction.destinationTokenAmount || "0",
546
- transaction.destinationToken.decimals,
547
- )}{" "}
548
- {transaction.destinationToken.symbol}
549
- </span>
561
+ <div className="flex flex-col gap-0.5">
562
+ <span
563
+ className="text-xs font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap overflow-hidden text-ellipsis"
564
+ style={{ maxWidth: "85px" }}
565
+ >
566
+ {formatRawAmount(
567
+ transaction.destinationTokenAmount || "0",
568
+ transaction.destinationToken.decimals,
569
+ )}{" "}
570
+ {transaction.destinationToken.symbol}
571
+ </span>
572
+ {transaction.destinationToAddress && (
573
+ <div className="flex items-center gap-1 whitespace-nowrap">
574
+ <Identicon
575
+ value={transaction.destinationToAddress}
576
+ size={12}
577
+ />
578
+ <span
579
+ className="text-xs"
580
+ style={{ color: "#71717A" }}
581
+ title={transaction.destinationToAddress}
582
+ >
583
+ {truncateAddress(transaction.destinationToAddress)}
584
+ </span>
585
+ </div>
586
+ )}
587
+ </div>
550
588
  </div>
551
589
  </div>
552
590
  ) : (
@@ -687,28 +725,36 @@ const TransactionItem: React.FC<{
687
725
  <ErrorDisplay error={recoverError} severity="error" />
688
726
  </div>
689
727
  )}
690
- <button
691
- type="button"
692
- onClick={() => setIsExpanded(true)}
693
- className="flex items-center justify-center gap-1 py-1 px-3 rounded-md transition-colors cursor-pointer text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700"
694
- aria-label="Show more details"
695
- >
696
- <span>More Details</span>
697
- <svg
698
- className="w-3 h-3 transition-transform duration-300 ease-out"
699
- fill="none"
700
- stroke="currentColor"
701
- viewBox="0 0 24 24"
702
- aria-hidden="true"
728
+ </div>
729
+
730
+ {/* Bottom section with status and more details button */}
731
+ <div className="flex items-center justify-between mt-2">
732
+ <ExecutionStatusBadge status={transaction.executionStatus} />
733
+ {!isExpanded && (
734
+ <button
735
+ type="button"
736
+ onClick={() => setIsExpanded(true)}
737
+ className="flex items-center justify-center gap-1 py-1 px-3 rounded-md transition-colors cursor-pointer text-xs text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700"
738
+ aria-label="Show more details"
703
739
  >
704
- <path
705
- strokeLinecap="round"
706
- strokeLinejoin="round"
707
- strokeWidth={2}
708
- d="M19 9l-7 7-7-7"
709
- />
710
- </svg>
711
- </button>
740
+ <span>More Details</span>
741
+ <svg
742
+ className="w-3 h-3 transition-transform duration-300 ease-out"
743
+ fill="none"
744
+ stroke="currentColor"
745
+ viewBox="0 0 24 24"
746
+ aria-hidden="true"
747
+ >
748
+ <title>Expand</title>
749
+ <path
750
+ strokeLinecap="round"
751
+ strokeLinejoin="round"
752
+ strokeWidth={2}
753
+ d="M19 9l-7 7-7-7"
754
+ />
755
+ </svg>
756
+ </button>
757
+ )}
712
758
  </div>
713
759
 
714
760
  {/* Details container */}
@@ -735,6 +781,7 @@ const TransactionItem: React.FC<{
735
781
  viewBox="0 0 24 24"
736
782
  aria-hidden="true"
737
783
  >
784
+ <title>Collapse</title>
738
785
  <path
739
786
  strokeLinecap="round"
740
787
  strokeLinejoin="round"
@@ -869,6 +916,7 @@ export const AccountIntentTransactionHistory: React.FC<
869
916
  string | null
870
917
  >(null)
871
918
  const walletDropdownRef = useRef<HTMLDivElement>(null)
919
+ const scrollContainerRef = useRef<HTMLDivElement>(null)
872
920
 
873
921
  const { address: currentAddress, connector } = useAccount()
874
922
  const connections = useConnections()
@@ -1117,6 +1165,7 @@ export const AccountIntentTransactionHistory: React.FC<
1117
1165
  stroke="currentColor"
1118
1166
  viewBox="0 0 24 24"
1119
1167
  >
1168
+ <title>Wallet Lock Icon</title>
1120
1169
  <path
1121
1170
  strokeLinecap="round"
1122
1171
  strokeLinejoin="round"
@@ -1161,6 +1210,7 @@ export const AccountIntentTransactionHistory: React.FC<
1161
1210
  stroke="currentColor"
1162
1211
  viewBox="0 0 24 24"
1163
1212
  >
1213
+ <title>Refresh</title>
1164
1214
  <path
1165
1215
  strokeLinecap="round"
1166
1216
  strokeLinejoin="round"
@@ -1245,6 +1295,7 @@ export const AccountIntentTransactionHistory: React.FC<
1245
1295
  stroke="currentColor"
1246
1296
  viewBox="0 0 24 24"
1247
1297
  >
1298
+ <title>Clear</title>
1248
1299
  <path
1249
1300
  strokeLinecap="round"
1250
1301
  strokeLinejoin="round"
@@ -1373,6 +1424,7 @@ export const AccountIntentTransactionHistory: React.FC<
1373
1424
  stroke="currentColor"
1374
1425
  viewBox="0 0 24 24"
1375
1426
  >
1427
+ <title>Error</title>
1376
1428
  <path
1377
1429
  strokeLinecap="round"
1378
1430
  strokeLinejoin="round"
@@ -1415,6 +1467,7 @@ export const AccountIntentTransactionHistory: React.FC<
1415
1467
  stroke="currentColor"
1416
1468
  viewBox="0 0 24 24"
1417
1469
  >
1470
+ <title>No Transactions</title>
1418
1471
  <path
1419
1472
  strokeLinecap="round"
1420
1473
  strokeLinejoin="round"
@@ -1442,6 +1495,7 @@ export const AccountIntentTransactionHistory: React.FC<
1442
1495
  stroke="currentColor"
1443
1496
  viewBox="0 0 24 24"
1444
1497
  >
1498
+ <title>No Results</title>
1445
1499
  <path
1446
1500
  strokeLinecap="round"
1447
1501
  strokeLinejoin="round"
@@ -1465,7 +1519,22 @@ export const AccountIntentTransactionHistory: React.FC<
1465
1519
  </div>
1466
1520
  </div>
1467
1521
  ) : (
1468
- <div className="flex-1 overflow-y-auto space-y-3 pr-2">
1522
+ <div
1523
+ ref={scrollContainerRef}
1524
+ className="flex-1 overflow-y-auto space-y-3 pr-2 relative"
1525
+ >
1526
+ {/* Loading overlay for pagination */}
1527
+ {loading && transactions.length > 0 && (
1528
+ <div className="absolute inset-0 bg-white/50 dark:bg-gray-900/50 backdrop-blur-sm z-10 flex items-center justify-center">
1529
+ <div className="flex flex-col items-center gap-2">
1530
+ <div className="animate-spin rounded-full h-10 w-10 border-b-2 border-blue-600 dark:border-blue-400"></div>
1531
+ <span className="text-sm text-gray-600 dark:text-gray-400">
1532
+ Loading...
1533
+ </span>
1534
+ </div>
1535
+ </div>
1536
+ )}
1537
+
1469
1538
  {/* Show fetched intent if available and not already in history */}
1470
1539
  {fetchedIntent && !existingIntentTransaction && (
1471
1540
  <div className="mb-3 p-3 border-2 border-blue-500 dark:border-blue-400 rounded-lg bg-blue-50 dark:bg-blue-900/20">
@@ -1475,7 +1544,7 @@ export const AccountIntentTransactionHistory: React.FC<
1475
1544
  FETCHED INTENT
1476
1545
  </span>
1477
1546
  <span className="text-xs text-gray-500 dark:text-gray-400">
1478
- {fetchedIntent.intentId.slice(0, 10)}...
1547
+ {truncateAddress(fetchedIntent.intentId)}
1479
1548
  </span>
1480
1549
  </div>
1481
1550
  <button
@@ -1545,7 +1614,13 @@ export const AccountIntentTransactionHistory: React.FC<
1545
1614
  <div className="flex items-center justify-center pt-2 mt-2 gap-4">
1546
1615
  <button
1547
1616
  type="button"
1548
- onClick={prevPage}
1617
+ onClick={() => {
1618
+ prevPage()
1619
+ scrollContainerRef.current?.scrollTo({
1620
+ top: 0,
1621
+ behavior: "smooth",
1622
+ })
1623
+ }}
1549
1624
  disabled={!hasPrev || loading}
1550
1625
  className="p-2 rounded-full transition-colors text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
1551
1626
  >
@@ -1555,6 +1630,7 @@ export const AccountIntentTransactionHistory: React.FC<
1555
1630
  stroke="currentColor"
1556
1631
  viewBox="0 0 24 24"
1557
1632
  >
1633
+ <title>Previous Page</title>
1558
1634
  <path
1559
1635
  strokeLinecap="round"
1560
1636
  strokeLinejoin="round"
@@ -1566,7 +1642,13 @@ export const AccountIntentTransactionHistory: React.FC<
1566
1642
 
1567
1643
  <button
1568
1644
  type="button"
1569
- onClick={nextPage}
1645
+ onClick={() => {
1646
+ nextPage()
1647
+ scrollContainerRef.current?.scrollTo({
1648
+ top: 0,
1649
+ behavior: "smooth",
1650
+ })
1651
+ }}
1570
1652
  disabled={!hasMore || loading}
1571
1653
  className="p-2 rounded-full transition-colors text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
1572
1654
  >
@@ -1576,6 +1658,7 @@ export const AccountIntentTransactionHistory: React.FC<
1576
1658
  stroke="currentColor"
1577
1659
  viewBox="0 0 24 24"
1578
1660
  >
1661
+ <title>Next Page</title>
1579
1662
  <path
1580
1663
  strokeLinecap="round"
1581
1664
  strokeLinejoin="round"
@@ -1061,7 +1061,13 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
1061
1061
  return (
1062
1062
  <div className="space-y-2">
1063
1063
  <ScreenHeader
1064
- onBack={mode === "fund" ? () => setCurrentScreen("fund-form") : onBack}
1064
+ onBack={
1065
+ mode === "fund"
1066
+ ? () => setCurrentScreen("fund-form")
1067
+ : mode === "earn"
1068
+ ? () => setCurrentScreen("earn")
1069
+ : onBack
1070
+ }
1065
1071
  headerContent={title}
1066
1072
  headerContentAlign="left"
1067
1073
  showAccountActions={true}
@@ -48,6 +48,11 @@ export const ConfigDisplay: React.FC<ConfigDisplayProps> = ({
48
48
  value: config.trailsApiUrl,
49
49
  display: truncateString(config.trailsApiUrl || "N/A"),
50
50
  },
51
+ {
52
+ label: "App URL",
53
+ value: config.trailsAppUrl,
54
+ display: truncateString(config.trailsAppUrl || "N/A"),
55
+ },
51
56
  {
52
57
  label: "Indexer URL",
53
58
  value: config.sequenceIndexerUrl,
@@ -4,12 +4,13 @@ import type { Account, WalletClient } from "viem"
4
4
  import type { TransactionState } from "../../transactions.js"
5
5
  import type { OnCompleteProps } from "../hooks/useSendForm.js"
6
6
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
7
- import { ArrowUpCircle, ArrowDownCircle } from "lucide-react"
7
+ import { ArrowUpCircle, ArrowDownCircle, ArrowLeftRight } from "lucide-react"
8
8
  import { ScreenHeader } from "./ScreenHeader.js"
9
9
  import { PoolDeposit } from "./PoolDeposit.js"
10
10
  import { PoolWithdraw } from "./PoolWithdraw.js"
11
11
  import type { PrepareSendQuote } from "../../prepareSend.js"
12
12
  import type { Token } from "../../tokens.js"
13
+ import { useBack } from "../hooks/useBack.js"
13
14
 
14
15
  interface EarnProps {
15
16
  onBack?: () => void
@@ -55,6 +56,7 @@ export const Earn: React.FC<EarnProps> = ({
55
56
  }) => {
56
57
  const [activeTab, setActiveTab] = useState<"deposit" | "withdraw">("deposit")
57
58
  const [isShowingPoolSelector, setIsShowingPoolSelector] = useState(false) // Track if pool selector is shown
59
+ const { setCurrentScreenWithBack } = useBack()
58
60
 
59
61
  return (
60
62
  <div className="space-y-2">
@@ -63,6 +65,17 @@ export const Earn: React.FC<EarnProps> = ({
63
65
  headerContent="Earn"
64
66
  headerContentAlign="left"
65
67
  showAccountActions={true}
68
+ customActions={
69
+ <button
70
+ type="button"
71
+ onClick={() => setCurrentScreenWithBack("swap", "earn")}
72
+ className="flex h-8 px-3 justify-center items-center gap-1.5 rounded-full bg-gray-50 dark:bg-gray-700 cursor-pointer transition-colors text-gray-900 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600"
73
+ title="Swap"
74
+ >
75
+ <ArrowLeftRight className="h-4 w-4" />
76
+ <span className="text-sm font-medium">Swap</span>
77
+ </button>
78
+ }
66
79
  />
67
80
 
68
81
  {/* Tabs - only show when not in pool selector mode */}