+
+
+
@@ -43,7 +47,7 @@ export const Receive = () => {
My Wallet
-
+
{
overflowWrap: 'anywhere'
}}
>
- {`This is a ${nativeTokenInfo.name} address. Please only send assets on the ${nativeTokenInfo.name} network.`}
+ {`This is a${isVowel(networkName[0]) ? 'n' : ''} ${networkName} address. Please only send assets on the ${networkName} network.`}
diff --git a/packages/wallet-widget/src/views/Search/SearchCollectibles.tsx b/packages/wallet-widget/src/views/Search/SearchCollectibles.tsx
new file mode 100644
index 000000000..689168d47
--- /dev/null
+++ b/packages/wallet-widget/src/views/Search/SearchCollectibles.tsx
@@ -0,0 +1,59 @@
+import { ContractVerificationStatus } from '@0xsequence/connect'
+import { useGetTokenBalancesDetails } from '@0xsequence/hooks'
+import { useObservable } from 'micro-observables'
+
+import { CollectiblesList } from '../../components/SearchLists/CollectiblesList'
+import { useSettings, useNavigation } from '../../hooks'
+import { TokenBalanceWithPrice } from '../../utils'
+
+export const SearchCollectibles = () => {
+ const { selectedWalletsObservable, selectedNetworksObservable, selectedCollectionsObservable, hideUnlistedTokens } =
+ useSettings()
+ const { setNavigation } = useNavigation()
+
+ const selectedWallets = useObservable(selectedWalletsObservable)
+ const selectedNetworks = useObservable(selectedNetworksObservable)
+ const selectedCollections = useObservable(selectedCollectionsObservable)
+
+ const { data: tokenBalancesData = [], isPending: isPendingTokenBalances } = useGetTokenBalancesDetails({
+ chainIds: selectedNetworks,
+ filter: {
+ accountAddresses: selectedWallets.map(wallet => wallet.address),
+ contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
+ contractWhitelist: selectedCollections.map(collection => collection.contractAddress),
+ omitNativeBalances: false
+ }
+ })
+
+ const isSingleCollectionSelected = selectedCollections.length === 1
+
+ const collectibleBalancesFiltered = tokenBalancesData.filter(token => {
+ if (isSingleCollectionSelected) {
+ return token.chainId === selectedCollections[0].chainId
+ }
+ return true
+ })
+
+ const onHandleCollectibleClick = (balance: TokenBalanceWithPrice) => {
+ setNavigation({
+ location: 'collectible-details',
+ params: {
+ contractAddress: balance.contractAddress,
+ chainId: balance.chainId,
+ tokenId: balance.tokenID || '',
+ accountAddress: balance.accountAddress
+ }
+ })
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Search/SearchTokens.tsx b/packages/wallet-widget/src/views/Search/SearchTokens.tsx
new file mode 100644
index 000000000..576aaf1d2
--- /dev/null
+++ b/packages/wallet-widget/src/views/Search/SearchTokens.tsx
@@ -0,0 +1,46 @@
+import { useGetTokenBalancesSummary } from '@0xsequence/hooks'
+import { ContractVerificationStatus } from '@0xsequence/indexer'
+import { useObservable } from 'micro-observables'
+
+import { TokenList } from '../../components/SearchLists'
+import { useNavigation, useSettings } from '../../hooks'
+import { TokenBalanceWithPrice } from '../../utils'
+
+export const SearchTokens = () => {
+ const { setNavigation } = useNavigation()
+ const { selectedWalletsObservable, selectedNetworksObservable, hideUnlistedTokens } = useSettings()
+
+ const selectedWallets = useObservable(selectedWalletsObservable)
+ const selectedNetworks = useObservable(selectedNetworksObservable)
+
+ const { data: tokenBalancesData = [], isPending: isPendingTokenBalances } = useGetTokenBalancesSummary({
+ chainIds: selectedNetworks,
+ filter: {
+ accountAddresses: selectedWallets.map(wallet => wallet.address),
+ contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
+ omitNativeBalances: false
+ }
+ })
+
+ const handleTokenClick = (balance: TokenBalanceWithPrice) => {
+ setNavigation({
+ location: 'coin-details',
+ params: {
+ contractAddress: balance.contractAddress,
+ chainId: balance.chainId,
+ accountAddress: balance.accountAddress
+ }
+ })
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Search/SearchWallet.tsx b/packages/wallet-widget/src/views/Search/SearchWallet.tsx
deleted file mode 100644
index fb45e1caf..000000000
--- a/packages/wallet-widget/src/views/Search/SearchWallet.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import { getNativeTokenInfoByChainId, ContractVerificationStatus, compareAddress } from '@0xsequence/connect'
-import { SearchIcon, Skeleton, Text, TextInput } from '@0xsequence/design-system'
-import { useGetTokenBalancesSummary, useGetCoinPrices, useGetExchangeRate } from '@0xsequence/hooks'
-import Fuse from 'fuse.js'
-import { useState } from 'react'
-import { zeroAddress } from 'viem'
-import { useAccount, useConfig } from 'wagmi'
-
-import { useSettings } from '../../hooks'
-import { computeBalanceFiat } from '../../utils'
-
-import { BalanceItem } from './components/BalanceItem'
-import { WalletLink } from './components/WalletLink'
-
-export const SearchWallet = () => {
- const { chains } = useConfig()
- const { fiatCurrency, hideUnlistedTokens, selectedNetworks } = useSettings()
- const [search, setSearch] = useState('')
- const { address: accountAddress } = useAccount()
-
- const { data: tokenBalancesData, isPending: isPendingTokenBalances } = useGetTokenBalancesSummary({
- chainIds: selectedNetworks,
- filter: {
- accountAddresses: accountAddress ? [accountAddress] : [],
- contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
- omitNativeBalances: false
- }
- })
-
- const coinBalancesUnordered =
- tokenBalancesData?.filter(b => b.contractType === 'ERC20' || compareAddress(b.contractAddress, zeroAddress)) || []
-
- const { data: coinPrices = [], isPending: isPendingCoinPrices } = useGetCoinPrices(
- coinBalancesUnordered.map(token => ({
- chainId: token.chainId,
- contractAddress: token.contractAddress
- }))
- )
-
- const { data: conversionRate = 1, isPending: isPendingConversionRate } = useGetExchangeRate(fiatCurrency.symbol)
-
- const coinBalances = coinBalancesUnordered.sort((a, b) => {
- const isHigherFiat =
- Number(
- computeBalanceFiat({
- balance: b,
- prices: coinPrices,
- conversionRate,
- decimals: b.contractInfo?.decimals || 18
- })
- ) -
- Number(
- computeBalanceFiat({
- balance: a,
- prices: coinPrices,
- conversionRate,
- decimals: a.contractInfo?.decimals || 18
- })
- )
- return isHigherFiat
- })
-
- const collectionBalancesUnordered =
- tokenBalancesData?.filter(b => b.contractType === 'ERC721' || b.contractType === 'ERC1155') || []
- const collectionBalances = collectionBalancesUnordered.sort((a, b) => {
- return Number(b.balance) - Number(a.balance)
- })
-
- const isPending = isPendingTokenBalances || isPendingCoinPrices || isPendingConversionRate
-
- interface IndexedData {
- index: number
- name: string
- }
- const indexedCollectionBalances: IndexedData[] = collectionBalances.map((balance, index) => {
- return {
- index,
- name: balance.contractInfo?.name || 'Unknown'
- }
- })
-
- const indexedCoinBalances: IndexedData[] = coinBalances.map((balance, index) => {
- if (compareAddress(balance.contractAddress, zeroAddress)) {
- const nativeTokenInfo = getNativeTokenInfoByChainId(balance.chainId, chains)
-
- return {
- index,
- name: nativeTokenInfo.name
- }
- } else {
- return {
- index,
- name: balance.contractInfo?.name || 'Unknown'
- }
- }
- })
-
- const coinBalancesAmount = coinBalances.length
- const collectionBalancesAmount = collectionBalances.length
-
- const fuzzySearchCoinBalances = new Fuse(indexedCoinBalances, {
- keys: ['name']
- })
-
- const fuzzySearchCollections = new Fuse(indexedCollectionBalances, {
- keys: ['name']
- })
-
- const foundCoinBalances = (
- search === '' ? indexedCoinBalances : fuzzySearchCoinBalances.search(search).map(result => result.item)
- ).slice(0, 5)
- const foundCollectionBalances = (
- search === '' ? indexedCollectionBalances : fuzzySearchCollections.search(search).map(result => result.item)
- ).slice(0, 5)
-
- return (
-
-
- setSearch(ev.target.value)}
- placeholder="Search your wallet"
- data-1p-ignore
- />
-
-
-
- {isPending ? (
- Array(5)
- .fill(null)
- .map((_, i) => )
- ) : foundCoinBalances.length === 0 ? (
- No coins found
- ) : (
- foundCoinBalances.map((indexItem, index) => {
- const balance = coinBalances[indexItem.index]
- return
- })
- )}
-
-
-
- {isPending ? (
- Array(5)
- .fill(null)
- .map((_, i) => )
- ) : foundCollectionBalances.length === 0 ? (
- No collections found
- ) : (
- foundCollectionBalances.map((indexedItem, index) => {
- const balance = collectionBalances[indexedItem.index]
- return
- })
- )}
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/SearchWalletViewAll.tsx b/packages/wallet-widget/src/views/Search/SearchWalletViewAll.tsx
deleted file mode 100644
index cbce5852e..000000000
--- a/packages/wallet-widget/src/views/Search/SearchWalletViewAll.tsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import { getNativeTokenInfoByChainId, ContractVerificationStatus, compareAddress } from '@0xsequence/connect'
-import { SearchIcon, Skeleton, TabsContent, TabsHeader, TabsRoot, TextInput } from '@0xsequence/design-system'
-import { useGetTokenBalancesSummary, useGetCoinPrices, useGetExchangeRate } from '@0xsequence/hooks'
-import Fuse from 'fuse.js'
-import { useState, useEffect } from 'react'
-import { zeroAddress } from 'viem'
-import { useAccount, useConfig } from 'wagmi'
-
-import { useSettings } from '../../hooks'
-import { computeBalanceFiat } from '../../utils'
-
-import { CoinsTab } from './components/CoinsTab'
-import { CollectionsTab } from './components/CollectionsTab'
-
-interface SearchWalletViewAllProps {
- defaultTab: 'coins' | 'collections'
-}
-
-export interface IndexedData {
- index: number
- name: string
-}
-
-export const SearchWalletViewAll = ({ defaultTab }: SearchWalletViewAllProps) => {
- const { chains } = useConfig()
- const { fiatCurrency, hideUnlistedTokens, selectedNetworks } = useSettings()
- const [search, setSearch] = useState('')
- const [selectedTab, setSelectedTab] = useState(defaultTab)
-
- const pageSize = 20
- const [displayedCoinBalances, setDisplayedCoinBalances] = useState
([])
- const [displayedCollectionBalances, setDisplayedCollectionBalances] = useState([])
-
- const [displayedSearchCoinBalances, setDisplayedSearchCoinBalances] = useState([])
- const [displayedSearchCollectionBalances, setDisplayedSearchCollectionBalances] = useState([])
-
- const [initCoinsFlag, setInitCoinsFlag] = useState(false)
- const [initCollectionsFlag, setInitCollectionsFlag] = useState(false)
-
- const [hasMoreCoins, sethasMoreCoins] = useState(false)
- const [hasMoreCollections, sethasMoreCollections] = useState(false)
-
- const [hasMoreSearchCoins, sethasMoreSearchCoins] = useState(false)
- const [hasMoreSearchCollections, sethasMoreSearchCollections] = useState(false)
-
- const { address: accountAddress } = useAccount()
-
- const { data: tokenBalancesData, isPending: isPendingTokenBalances } = useGetTokenBalancesSummary({
- chainIds: selectedNetworks,
- filter: {
- accountAddresses: accountAddress ? [accountAddress] : [],
- contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
- omitNativeBalances: false
- }
- })
-
- const coinBalancesUnordered =
- tokenBalancesData?.filter(b => b.contractType === 'ERC20' || compareAddress(b.contractAddress, zeroAddress)) || []
-
- const { data: coinPrices = [], isPending: isPendingCoinPrices } = useGetCoinPrices(
- coinBalancesUnordered.map(token => ({
- chainId: token.chainId,
- contractAddress: token.contractAddress
- }))
- )
-
- const { data: conversionRate = 1, isPending: isPendingConversionRate } = useGetExchangeRate(fiatCurrency.symbol)
-
- const coinBalances = coinBalancesUnordered.sort((a, b) => {
- const fiatA = computeBalanceFiat({
- balance: a,
- prices: coinPrices,
- conversionRate,
- decimals: a.contractInfo?.decimals || 18
- })
- const fiatB = computeBalanceFiat({
- balance: b,
- prices: coinPrices,
- conversionRate,
- decimals: b.contractInfo?.decimals || 18
- })
- return Number(fiatB) - Number(fiatA)
- })
-
- const collectionBalancesUnordered =
- tokenBalancesData?.filter(b => b.contractType === 'ERC721' || b.contractType === 'ERC1155') || []
-
- const collectionBalances = collectionBalancesUnordered.sort((a, b) => {
- return Number(b.balance) - Number(a.balance)
- })
-
- const coinBalancesAmount = coinBalances.length
- const collectionBalancesAmount = collectionBalances.length
-
- const isPending = isPendingTokenBalances || isPendingCoinPrices || isPendingConversionRate
-
- const indexedCoinBalances: IndexedData[] = coinBalances.map((balance, index) => {
- if (compareAddress(balance.contractAddress, zeroAddress)) {
- const nativeTokenInfo = getNativeTokenInfoByChainId(balance.chainId, chains)
-
- return {
- index,
- name: nativeTokenInfo.name
- }
- } else {
- return {
- index,
- name: balance.contractInfo?.name || 'Unknown'
- }
- }
- })
-
- const indexedCollectionBalances: IndexedData[] = collectionBalances.map((balance, index) => ({
- index,
- name: balance.contractInfo?.name || 'Unknown'
- }))
-
- useEffect(() => {
- if (!initCoinsFlag && indexedCoinBalances.length > 0) {
- setDisplayedCoinBalances(indexedCoinBalances.slice(0, pageSize))
- sethasMoreCoins(indexedCoinBalances.length > pageSize)
- setInitCoinsFlag(true)
- }
- }, [initCoinsFlag])
-
- useEffect(() => {
- if (!initCollectionsFlag && indexedCollectionBalances.length > 0) {
- setDisplayedCollectionBalances(indexedCollectionBalances.slice(0, pageSize))
- sethasMoreCollections(indexedCollectionBalances.length > pageSize)
- setInitCollectionsFlag(true)
- }
- }, [initCollectionsFlag])
-
- useEffect(() => {
- if (search !== '') {
- setDisplayedSearchCoinBalances(
- fuzzySearchCoinBalances
- .search(search)
- .map(result => result.item)
- .slice(0, pageSize)
- )
- sethasMoreSearchCoins(fuzzySearchCoinBalances.search(search).length > pageSize)
- }
- }, [search])
-
- useEffect(() => {
- if (search !== '') {
- setDisplayedSearchCollectionBalances(
- fuzzySearchCollections
- .search(search)
- .map(result => result.item)
- .slice(0, pageSize)
- )
- sethasMoreSearchCollections(fuzzySearchCollections.search(search).length > pageSize)
- }
- }, [search])
-
- const fetchMoreCoinBalances = () => {
- if (displayedCoinBalances.length >= indexedCoinBalances.length) {
- sethasMoreCoins(false)
- return
- }
- setDisplayedCoinBalances(indexedCoinBalances.slice(0, displayedCoinBalances.length + pageSize))
- }
-
- const fetchMoreCollectionBalances = () => {
- if (displayedCollectionBalances.length >= indexedCollectionBalances.length) {
- sethasMoreCollections(false)
- return
- }
- setDisplayedCollectionBalances(indexedCollectionBalances.slice(0, displayedCollectionBalances.length + pageSize))
- }
-
- const fetchMoreSearchCoinBalances = () => {
- if (displayedSearchCoinBalances.length >= fuzzySearchCoinBalances.search(search).length) {
- sethasMoreSearchCoins(false)
- return
- }
- setDisplayedSearchCoinBalances(
- fuzzySearchCoinBalances
- .search(search)
- .map(result => result.item)
- .slice(0, displayedSearchCoinBalances.length + pageSize)
- )
- }
-
- const fetchMoreSearchCollectionBalances = () => {
- if (displayedSearchCollectionBalances.length >= fuzzySearchCollections.search(search).length) {
- sethasMoreSearchCollections(false)
- return
- }
- setDisplayedSearchCollectionBalances(
- fuzzySearchCollections
- .search(search)
- .map(result => result.item)
- .slice(0, displayedSearchCollectionBalances.length + pageSize)
- )
- }
-
- const fuzzySearchCoinBalances = new Fuse(indexedCoinBalances, {
- keys: ['name']
- })
-
- const fuzzySearchCollections = new Fuse(indexedCollectionBalances, {
- keys: ['name']
- })
-
- return (
-
-
- setSearch(ev.target.value)}
- placeholder="Search your wallet"
- data-1p-ignore
- />
-
-
-
setSelectedTab(value as 'coins' | 'collections')}>
-
- {!isPending && (
-
- )}
- {isPending && }
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/components/BalanceItem.tsx b/packages/wallet-widget/src/views/Search/components/BalanceItem.tsx
deleted file mode 100644
index e2f49d4bc..000000000
--- a/packages/wallet-widget/src/views/Search/components/BalanceItem.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { compareAddress, formatDisplay, getNativeTokenInfoByChainId } from '@0xsequence/connect'
-import { Text, ChevronRightIcon, TokenImage } from '@0xsequence/design-system'
-import { TokenBalance } from '@0xsequence/indexer'
-import React from 'react'
-import { formatUnits, zeroAddress } from 'viem'
-import { useConfig } from 'wagmi'
-
-import { useNavigation } from '../../../hooks'
-
-interface BalanceItemProps {
- balance: TokenBalance
-}
-
-export const BalanceItem = ({ balance }: BalanceItemProps) => {
- const { chains } = useConfig()
- const { setNavigation } = useNavigation()
- const isNativeToken = compareAddress(balance.contractAddress, zeroAddress)
- const nativeTokenInfo = getNativeTokenInfoByChainId(balance.chainId, chains)
- const logoURI = isNativeToken ? nativeTokenInfo.logoURI : balance?.contractInfo?.logoURI
- const tokenName = isNativeToken ? nativeTokenInfo.name : balance?.contractInfo?.name || 'Unknown'
- const symbol = isNativeToken ? nativeTokenInfo.symbol : balance?.contractInfo?.symbol
-
- const getQuantity = () => {
- if (balance.contractType === 'ERC721' || balance.contractType === 'ERC1155') {
- return balance.uniqueCollectibles
- }
- const decimals = isNativeToken ? nativeTokenInfo.decimals : balance?.contractInfo?.decimals
- const bal = formatUnits(BigInt(balance.balance), decimals || 0)
- const displayBalance = formatDisplay(bal)
- const symbol = isNativeToken ? nativeTokenInfo.symbol : balance?.contractInfo?.symbol
-
- return `${displayBalance} ${symbol}`
- }
-
- const onClick = () => {
- const isCollection = balance.contractType === 'ERC721' || balance.contractType === 'ERC1155'
- if (isCollection) {
- setNavigation({
- location: 'collection-details',
- params: {
- contractAddress: balance.contractAddress,
- chainId: balance.chainId
- }
- })
- } else {
- setNavigation({
- location: 'coin-details',
- params: {
- contractAddress: balance.contractAddress,
- chainId: balance.chainId
- }
- })
- }
- }
-
- return (
-
-
-
-
- {tokenName}
-
-
-
-
- {getQuantity()}
-
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/components/CoinsTab.tsx b/packages/wallet-widget/src/views/Search/components/CoinsTab.tsx
deleted file mode 100644
index 9b60de348..000000000
--- a/packages/wallet-widget/src/views/Search/components/CoinsTab.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { Spinner, Skeleton, Text } from '@0xsequence/design-system'
-import { TokenBalance } from '@0xsequence/indexer'
-import React, { useEffect, useRef, useState } from 'react'
-
-import { IndexedData } from '../SearchWalletViewAll'
-
-import { BalanceItem } from './BalanceItem'
-
-interface CoinsTabProps {
- displayedCoinBalances: IndexedData[]
- fetchMoreCoinBalances: () => void
- fetchMoreSearchCoinBalances: () => void
- hasMoreCoins: boolean
- hasMoreSearchCoins: boolean
- isSearching: boolean
- isPending: boolean
- coinBalances: TokenBalance[]
-}
-
-export const CoinsTab: React.FC = ({
- displayedCoinBalances,
- fetchMoreCoinBalances,
- fetchMoreSearchCoinBalances,
- hasMoreCoins,
- hasMoreSearchCoins,
- isSearching,
- isPending,
- coinBalances
-}) => {
- const [isLoading, setIsLoading] = useState(false)
-
- const endOfPageRefCoins = useRef(null)
-
- useEffect(() => {
- if (!endOfPageRefCoins.current) {
- return
- }
-
- const observer = new IntersectionObserver(entries => {
- const endOfPage = entries[0]
- if (!endOfPage.isIntersecting) {
- return
- }
- if (isSearching && hasMoreSearchCoins) {
- setIsLoading(true)
- setTimeout(() => {
- fetchMoreSearchCoinBalances()
- setIsLoading(false)
- }, 500)
- } else if (!isSearching && hasMoreCoins) {
- setIsLoading(true)
- setTimeout(() => {
- fetchMoreCoinBalances()
- setIsLoading(false)
- }, 500)
- }
- })
-
- observer.observe(endOfPageRefCoins.current)
-
- return () => {
- observer.disconnect()
- }
- }, [fetchMoreCoinBalances, fetchMoreSearchCoinBalances, isSearching])
-
- return (
-
-
- {isPending && (
- <>
- {Array(8)
- .fill(null)
- .map((_, i) => (
-
- ))}
- >
- )}
- {!isPending && displayedCoinBalances.length === 0 && No Coins Found }
- {!isPending &&
- displayedCoinBalances.map((indexItem, index) => {
- const balance = coinBalances[indexItem.index]
- return
- })}
- {isLoading && }
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/components/CollectionsTab.tsx b/packages/wallet-widget/src/views/Search/components/CollectionsTab.tsx
deleted file mode 100644
index 62aace2e1..000000000
--- a/packages/wallet-widget/src/views/Search/components/CollectionsTab.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import { Spinner, Skeleton, Text } from '@0xsequence/design-system'
-import { TokenBalance } from '@0xsequence/indexer'
-import React, { useEffect, useRef, useState } from 'react'
-
-import { IndexedData } from '../SearchWalletViewAll'
-
-import { BalanceItem } from './BalanceItem'
-
-interface CollectionsTabProps {
- displayedCollectionBalances: IndexedData[]
- fetchMoreCollectionBalances: () => void
- fetchMoreSearchCollectionBalances: () => void
- hasMoreCollections: boolean
- hasMoreSearchCollections: boolean
- isSearching: boolean
- isPending: boolean
- collectionBalances: TokenBalance[]
-}
-
-export const CollectionsTab: React.FC = ({
- displayedCollectionBalances,
- fetchMoreCollectionBalances,
- fetchMoreSearchCollectionBalances,
- hasMoreCollections,
- hasMoreSearchCollections,
- isSearching,
- isPending,
- collectionBalances
-}) => {
- const [isLoading, setIsLoading] = useState(false)
-
- const endOfPageRefCollections = useRef(null)
-
- useEffect(() => {
- if (!endOfPageRefCollections.current) {
- return
- }
-
- const observer = new IntersectionObserver(entries => {
- const endOfPage = entries[0]
- if (!endOfPage.isIntersecting) {
- return
- }
- if (isSearching && hasMoreSearchCollections) {
- setIsLoading(true)
- setTimeout(() => {
- fetchMoreSearchCollectionBalances()
- setIsLoading(false)
- }, 500)
- } else if (!isSearching && hasMoreCollections) {
- setIsLoading(true)
- setTimeout(() => {
- fetchMoreCollectionBalances()
- setIsLoading(false)
- }, 500)
- }
- })
- observer.observe(endOfPageRefCollections.current)
-
- return () => {
- observer.disconnect()
- }
- }, [fetchMoreCollectionBalances, fetchMoreSearchCollectionBalances, isSearching])
-
- return (
-
-
- {isPending && (
- <>
- {Array(8)
- .fill(null)
- .map((_, i) => (
-
- ))}
- >
- )}
- {!isPending && displayedCollectionBalances.length === 0 && No Collectibles Found }
- {!isPending &&
- displayedCollectionBalances.map((indexItem, index) => {
- const balance = collectionBalances[indexItem.index]
- return
- })}
- {isLoading && }
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/components/WalletLink.tsx b/packages/wallet-widget/src/views/Search/components/WalletLink.tsx
deleted file mode 100644
index 7074b27e2..000000000
--- a/packages/wallet-widget/src/views/Search/components/WalletLink.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Text, ChevronRightIcon } from '@0xsequence/design-system'
-import React from 'react'
-
-import { Navigation } from '../../../contexts'
-import { useNavigation } from '../../../hooks'
-
-interface WalletLinkProps {
- toLocation: Navigation
- label: string
-}
-
-export const WalletLink = ({ toLocation, label }: WalletLinkProps) => {
- const { setNavigation } = useNavigation()
-
- const onClick = () => {
- setNavigation(toLocation)
- }
-
- return (
-
-
- {label}
-
-
-
- View all
-
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Search/index.ts b/packages/wallet-widget/src/views/Search/index.ts
index 7b706a865..184260b4b 100644
--- a/packages/wallet-widget/src/views/Search/index.ts
+++ b/packages/wallet-widget/src/views/Search/index.ts
@@ -1,2 +1,2 @@
-export * from './SearchWallet'
-export * from './SearchWalletViewAll'
+export * from './SearchTokens'
+export * from './SearchCollectibles'
diff --git a/packages/wallet-widget/src/views/SendCoin.tsx b/packages/wallet-widget/src/views/Send/SendCoin.tsx
similarity index 81%
rename from packages/wallet-widget/src/views/SendCoin.tsx
rename to packages/wallet-widget/src/views/Send/SendCoin.tsx
index 9633a78d5..0ccf72d4f 100644
--- a/packages/wallet-widget/src/views/SendCoin.tsx
+++ b/packages/wallet-widget/src/views/Send/SendCoin.tsx
@@ -7,7 +7,8 @@ import {
useCheckWaasFeeOptions,
useWaasFeeOptions,
waitForTransactionReceipt,
- TRANSACTION_CONFIRMATIONS_DEFAULT
+ TRANSACTION_CONFIRMATIONS_DEFAULT,
+ useWallets
} from '@0xsequence/connect'
import {
Button,
@@ -19,7 +20,8 @@ import {
NumericInput,
TextInput,
Spinner,
- Card
+ Card,
+ useToast
} from '@0xsequence/design-system'
import {
useClearCachedBalances,
@@ -33,12 +35,13 @@ import { useState, ChangeEvent, useRef, useEffect } from 'react'
import { encodeFunctionData, formatUnits, parseUnits, toHex, zeroAddress, Hex } from 'viem'
import { useAccount, useChainId, useSwitchChain, useConfig, useSendTransaction, usePublicClient } from 'wagmi'
-import { SendItemInfo } from '../components/SendItemInfo'
-import { TransactionConfirmation } from '../components/TransactionConfirmation'
-import { ERC_20_ABI, HEADER_HEIGHT } from '../constants'
-import { useNavigationContext } from '../contexts/Navigation'
-import { useSettings, useNavigation } from '../hooks'
-import { computeBalanceFiat, limitDecimals, isEthAddress } from '../utils'
+import { WalletSelect } from '../../components/Select/WalletSelect'
+import { SendItemInfo } from '../../components/SendItemInfo'
+import { TransactionConfirmation } from '../../components/TransactionConfirmation'
+import { ERC_20_ABI, HEADER_HEIGHT_WITH_LABEL } from '../../constants'
+import { useNavigationContext } from '../../contexts/Navigation'
+import { useSettings, useNavigation } from '../../hooks'
+import { computeBalanceFiat, limitDecimals, isEthAddress } from '../../utils'
interface SendCoinProps {
chainId: number
@@ -49,6 +52,8 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
const { clearCachedBalances } = useClearCachedBalances()
const publicClient = usePublicClient({ chainId })
const indexerClient = useIndexerClient(chainId)
+ const toast = useToast()
+ const { wallets } = useWallets()
const { setNavigation } = useNavigation()
const { setIsBackButtonEnabled } = useNavigationContext()
const { analytics } = useAnalyticsContext()
@@ -56,8 +61,8 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
const connectedChainId = useChainId()
const { address: accountAddress = '', connector } = useAccount()
const isConnectorSequenceBased = !!(connector as ExtendedConnector)?._wallet?.isSequenceBased
+ const isConnectorWaas = !!(connector as ExtendedConnector)?.type?.includes('waas')
const isCorrectChainId = connectedChainId === chainId
- const showSwitchNetwork = !isCorrectChainId && !isConnectorSequenceBased
const { switchChainAsync } = useSwitchChain()
const amountInputRef = useRef(null)
const { fiatCurrency } = useSettings()
@@ -165,6 +170,15 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
const handleSendClick = async (e: ChangeEvent) => {
e.preventDefault()
+ if (!isCorrectChainId && !isConnectorSequenceBased) {
+ await switchChainAsync({ chainId })
+ }
+
+ if (!isConnectorWaas) {
+ executeTransaction()
+ return
+ }
+
setIsCheckingFeeOptions(true)
const sendAmount = parseUnits(amountToSendFormatted, decimals)
@@ -238,6 +252,13 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
clearCachedBalances()
}
}
+ setIsSendTxnPending(false)
+
+ toast({
+ title: 'Transaction sent',
+ description: `Successfully sent ${amountToSendFormatted} ${symbol} to ${toAddress}`,
+ variant: 'success'
+ })
}
}
@@ -264,9 +285,9 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
return (
+
{isCheckingFeeOptions ? (
) : (
@@ -404,6 +398,7 @@ export const SendCoin = ({ chainId, contractAddress }: SendCoinProps) => {
setSelectedFeeTokenAddress(feeTokenAddress)
}}
isLoading={isSendTxnPending}
+ disabled={!isCorrectChainId && !isConnectorSequenceBased}
onConfirm={() => {
executeTransaction()
}}
diff --git a/packages/wallet-widget/src/views/SendCollectible.tsx b/packages/wallet-widget/src/views/Send/SendCollectible.tsx
similarity index 84%
rename from packages/wallet-widget/src/views/SendCollectible.tsx
rename to packages/wallet-widget/src/views/Send/SendCollectible.tsx
index d231b97af..f088367c3 100644
--- a/packages/wallet-widget/src/views/SendCollectible.tsx
+++ b/packages/wallet-widget/src/views/Send/SendCollectible.tsx
@@ -6,7 +6,8 @@ import {
useCheckWaasFeeOptions,
useWaasFeeOptions,
waitForTransactionReceipt,
- TRANSACTION_CONFIRMATIONS_DEFAULT
+ TRANSACTION_CONFIRMATIONS_DEFAULT,
+ useWallets
} from '@0xsequence/connect'
import {
Button,
@@ -20,7 +21,8 @@ import {
NumericInput,
TextInput,
Spinner,
- Card
+ Card,
+ useToast
} from '@0xsequence/design-system'
import { useGetTokenBalancesDetails, useClearCachedBalances, useIndexerClient } from '@0xsequence/hooks'
import { ContractType, ContractVerificationStatus, TokenBalance } from '@0xsequence/indexer'
@@ -28,12 +30,13 @@ import { useRef, useState, ChangeEvent, useEffect } from 'react'
import { encodeFunctionData, formatUnits, parseUnits, toHex, Hex } from 'viem'
import { useAccount, useChainId, useSwitchChain, useConfig, useSendTransaction, usePublicClient } from 'wagmi'
-import { SendItemInfo } from '../components/SendItemInfo'
-import { TransactionConfirmation } from '../components/TransactionConfirmation'
-import { ERC_1155_ABI, ERC_721_ABI, HEADER_HEIGHT } from '../constants'
-import { useNavigationContext } from '../contexts/Navigation'
-import { useNavigation } from '../hooks'
-import { limitDecimals, isEthAddress } from '../utils'
+import { WalletSelect } from '../../components/Select/WalletSelect'
+import { SendItemInfo } from '../../components/SendItemInfo'
+import { TransactionConfirmation } from '../../components/TransactionConfirmation'
+import { ERC_1155_ABI, ERC_721_ABI, HEADER_HEIGHT_WITH_LABEL } from '../../constants'
+import { useNavigationContext } from '../../contexts/Navigation'
+import { useNavigation } from '../../hooks'
+import { limitDecimals, isEthAddress } from '../../utils'
interface SendCollectibleProps {
chainId: number
@@ -42,6 +45,8 @@ interface SendCollectibleProps {
}
export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendCollectibleProps) => {
+ const toast = useToast()
+ const { wallets } = useWallets()
const { setNavigation } = useNavigation()
const { setIsBackButtonEnabled } = useNavigationContext()
const { analytics } = useAnalyticsContext()
@@ -51,10 +56,10 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
const indexerClient = useIndexerClient(chainId)
const publicClient = usePublicClient({ chainId })
const isConnectorSequenceBased = !!(connector as ExtendedConnector)?._wallet?.isSequenceBased
+ const isConnectorWaas = !!(connector as ExtendedConnector)?.type?.includes('waas')
const isCorrectChainId = connectedChainId === chainId
- const showSwitchNetwork = !isCorrectChainId && !isConnectorSequenceBased
- const { switchChain } = useSwitchChain()
const { clearCachedBalances } = useClearCachedBalances()
+ const { switchChainAsync } = useSwitchChain()
const amountInputRef = useRef(null)
const [amount, setAmount] = useState('0')
const [toAddress, setToAddress] = useState('')
@@ -178,6 +183,15 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
const handleSendClick = async (e: ChangeEvent) => {
e.preventDefault()
+ if (!isCorrectChainId && !isConnectorSequenceBased) {
+ await switchChainAsync({ chainId })
+ }
+
+ if (!isConnectorWaas) {
+ executeTransaction()
+ return
+ }
+
setIsCheckingFeeOptions(true)
const sendAmount = parseUnits(amountToSendFormatted, decimals)
@@ -228,7 +242,7 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
const executeTransaction = async () => {
if (!isCorrectChainId && isConnectorSequenceBased) {
- switchChain({ chainId })
+ await switchChainAsync({ chainId })
}
const sendAmount = parseUnits(amountToSendFormatted, decimals)
@@ -252,6 +266,12 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
})
clearCachedBalances()
}
+
+ toast({
+ title: 'Transaction sent',
+ description: `Successfully sent ${amountToSendFormatted} ${name} to ${toAddress}`,
+ variant: 'success'
+ })
}
}
@@ -312,9 +332,9 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
return (
- {showSwitchNetwork && (
-
-
- The wallet is connected to the wrong network. Please switch network before proceeding
-
- switchChain({ chainId })}
- disabled={isCorrectChainId}
- />
-
- )}
-
-
+
{isCheckingFeeOptions ? (
) : (
@@ -448,6 +449,7 @@ export const SendCollectible = ({ chainId, contractAddress, tokenId }: SendColle
setSelectedFeeTokenAddress(feeTokenAddress)
}}
isLoading={isSendTxnPending}
+ disabled={!isCorrectChainId && !isConnectorSequenceBased}
onConfirm={() => {
executeTransaction()
}}
diff --git a/packages/wallet-widget/src/views/Send/SendGeneral.tsx b/packages/wallet-widget/src/views/Send/SendGeneral.tsx
new file mode 100644
index 000000000..d0afa9b36
--- /dev/null
+++ b/packages/wallet-widget/src/views/Send/SendGeneral.tsx
@@ -0,0 +1,92 @@
+import { useWallets } from '@0xsequence/connect'
+import { TabsHeader, TabsContent, TabsRoot } from '@0xsequence/design-system'
+import { useGetTokenBalancesDetails, useGetTokenBalancesSummary } from '@0xsequence/hooks'
+import { ContractVerificationStatus } from '@0xsequence/indexer'
+import { useState } from 'react'
+
+import { CollectiblesList, TokenList } from '../../components/SearchLists'
+import { useSettings, useNavigation } from '../../hooks'
+import { TokenBalanceWithPrice } from '../../utils/tokens'
+
+export const SendGeneral = () => {
+ const { setNavigation } = useNavigation()
+ const { wallets } = useWallets()
+ const { allNetworks, hideUnlistedTokens } = useSettings()
+ const [selectedTab, setSelectedTab] = useState<'coins' | 'collectibles'>('coins')
+
+ const activeWallet = wallets.find(wallet => wallet.isActive)
+
+ const { data: tokenBalancesData = [], isPending: isPendingTokenBalances } = useGetTokenBalancesSummary({
+ chainIds: allNetworks,
+ filter: {
+ accountAddresses: [activeWallet?.address || ''],
+ contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
+ omitNativeBalances: false
+ }
+ })
+
+ const { data: collectibleBalancesData = [], isPending: isPendingCollectibleBalances } = useGetTokenBalancesDetails({
+ chainIds: allNetworks,
+ filter: {
+ accountAddresses: [activeWallet?.address || ''],
+ contractStatus: hideUnlistedTokens ? ContractVerificationStatus.VERIFIED : ContractVerificationStatus.ALL,
+ omitNativeBalances: false
+ }
+ })
+
+ const handleTokenClick = (token: TokenBalanceWithPrice) => {
+ setNavigation({
+ location: 'send-coin',
+ params: {
+ chainId: token.chainId,
+ contractAddress: token.contractAddress
+ }
+ })
+ }
+
+ const handleCollectibleClick = (token: TokenBalanceWithPrice) => {
+ setNavigation({
+ location: 'send-collectible',
+ params: {
+ chainId: token.chainId,
+ contractAddress: token.contractAddress,
+ tokenId: token.tokenID || ''
+ }
+ })
+ }
+
+ return (
+
+ setSelectedTab(value as 'coins' | 'collectibles')}
+ >
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Send/index.ts b/packages/wallet-widget/src/views/Send/index.ts
new file mode 100644
index 000000000..160a6fb0a
--- /dev/null
+++ b/packages/wallet-widget/src/views/Send/index.ts
@@ -0,0 +1,3 @@
+export * from './SendGeneral'
+export * from './SendCoin'
+export * from './SendCollectible'
diff --git a/packages/wallet-widget/src/views/Settings/Apps.tsx b/packages/wallet-widget/src/views/Settings/Apps.tsx
new file mode 100644
index 000000000..64d9d771f
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/Apps.tsx
@@ -0,0 +1,14 @@
+import { OptionsFooter } from '../../components/OptionsFooter'
+import { useNavigation } from '../../hooks/useNavigation'
+
+export const SettingsApps = () => {
+ const { setNavigation } = useNavigation()
+ const onClickConnectApp = () => {
+ setNavigation({ location: 'connect-dapp' })
+ }
+ return (
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/Currency.tsx b/packages/wallet-widget/src/views/Settings/Currency.tsx
index 7d922a267..8d63b5691 100644
--- a/packages/wallet-widget/src/views/Settings/Currency.tsx
+++ b/packages/wallet-widget/src/views/Settings/Currency.tsx
@@ -1,31 +1,29 @@
import { Text } from '@0xsequence/design-system'
-import React from 'react'
+import { useObservable } from 'micro-observables'
-import { SelectButton } from '../../components/SelectButton'
+import { ListCardSelect } from '../../components/ListCard/ListCardSelect'
import { supportedFiatCurrencies } from '../../constants'
import { useSettings } from '../../hooks'
export const SettingsCurrency = () => {
- const { fiatCurrency, setFiatCurrency } = useSettings()
+ const { fiatCurrencyObservable, setFiatCurrency } = useSettings()
+ const fiatCurrency = useObservable(fiatCurrencyObservable)
return (
-
+
- {supportedFiatCurrencies.map(currency => {
+ {supportedFiatCurrencies.map((currency, index) => {
return (
-
setFiatCurrency && setFiatCurrency(currency)}
>
-
-
- {currency.symbol}
-
- {currency.name.message}
-
-
+
+ {currency.symbol}
+
+
{currency.name.message}
+
)
})}
diff --git a/packages/wallet-widget/src/views/Settings/General.tsx b/packages/wallet-widget/src/views/Settings/General.tsx
deleted file mode 100644
index 0777e17cd..000000000
--- a/packages/wallet-widget/src/views/Settings/General.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import { Card, Switch, Text } from '@0xsequence/design-system'
-// import { useTheme } from '@0xsequence/connect'
-import React from 'react'
-
-import { HEADER_HEIGHT } from '../../constants'
-import { useSettings } from '../../hooks'
-
-export const SettingsGeneral = () => {
- // const { theme, setTheme } = useTheme()
- const { hideUnlistedTokens, setHideUnlistedTokens, hideCollectibles, setHideCollectibles } = useSettings()
-
- // const onChangeTheme = () => {
- // setTheme && setTheme(theme === 'light' ? 'dark' : 'light')
- // }
-
- const onChangeHideUnlistedTokens = () => {
- setHideUnlistedTokens(!hideUnlistedTokens)
- }
-
- const onChangeHideCollectibles = () => {
- setHideCollectibles(!hideCollectibles)
- }
-
- return (
-
-
- {/*
-
- Dark mode
-
-
- */}
-
-
- Hide unlisted tokens
-
-
-
-
-
- Hide collectibles
-
-
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Settings/Menu.tsx b/packages/wallet-widget/src/views/Settings/Menu.tsx
index 444ac8009..4fded0b12 100644
--- a/packages/wallet-widget/src/views/Settings/Menu.tsx
+++ b/packages/wallet-widget/src/views/Settings/Menu.tsx
@@ -1,59 +1,112 @@
-import { Button, SettingsIcon, ChevronRightIcon, CurrencyIcon, NetworkIcon } from '@0xsequence/design-system'
-import React from 'react'
+import { useWallets } from '@0xsequence/connect'
+import { CurrencyIcon, NetworkIcon, Text, WalletIcon } from '@0xsequence/design-system'
+import { StackedIconTag } from '../../components/IconWrappers/StackedIconTag'
+import { ListCardNav } from '../../components/ListCard/ListCardNav'
import { HEADER_HEIGHT } from '../../constants'
-import { useNavigation } from '../../hooks'
+import { useNavigation, useSettings } from '../../hooks'
export const SettingsMenu = () => {
+ const { wallets } = useWallets()
+ const { selectedNetworks, fiatCurrency } = useSettings()
+ // const activeWallet = wallets.find(wallet => wallet.isActive)
+ // const isEmbedded = activeWallet?.id.includes('waas')
+
const { setNavigation } = useNavigation()
- const onClickGeneral = () => {
+ const onClickWallets = () => {
setNavigation({
- location: 'settings-general'
+ location: 'settings-wallets'
})
}
+ const onClickNetworks = () => {
+ setNavigation({
+ location: 'settings-networks'
+ })
+ }
+
+ // const onClickProfiles = () => {
+ // setNavigation({
+ // location: 'settings-profiles'
+ // })
+ // }
+
+ // const onClickApps = () => {
+ // setNavigation({
+ // location: 'settings-apps'
+ // })
+ // }
+
const onClickCurrency = () => {
setNavigation({
location: 'settings-currency'
})
}
- const onClickNetworks = () => {
+ const onClickPreferences = () => {
setNavigation({
- location: 'settings-networks'
+ location: 'settings-preferences'
})
}
+ const walletsPreview = (
+
{wallets.length}}
+ iconList={wallets.map(wallet => wallet.address)}
+ shape="rounded"
+ isAccount
+ />
+ )
+
+ const networksPreview = (
+ {selectedNetworks.length}}
+ iconList={selectedNetworks.map(network => {
+ return `https://assets.sequence.info/images/networks/medium/${network}.webp`
+ })}
+ />
+ )
+
+ const currencyPreview = (
+
+ {fiatCurrency.symbol} {fiatCurrency.sign}
+
+ )
+
return (
-
-
-
-
-
-
-
+
+
+
+
+
+ Manage Wallets
+
+
+
+
+
+ Manage Networks
+
+
+
+
+
+ Manage Currency
+
+
+ {/* {isEmbedded && (
+
+
+ Manage Profiles
+
+
+ )} */}
+
+
+ Preferences
+
+
)
diff --git a/packages/wallet-widget/src/views/Settings/Network.tsx b/packages/wallet-widget/src/views/Settings/Network.tsx
deleted file mode 100644
index 26792b31b..000000000
--- a/packages/wallet-widget/src/views/Settings/Network.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useWalletSettings } from '@0xsequence/connect'
-import { Text, TokenImage } from '@0xsequence/design-system'
-import { ChainId } from '@0xsequence/network'
-import { useConfig } from 'wagmi'
-
-import { SelectButton } from '../../components/SelectButton'
-import { HEADER_HEIGHT } from '../../constants'
-import { useSettings } from '../../hooks'
-
-export const SettingsNetwork = () => {
- const { readOnlyNetworks, displayedAssets } = useWalletSettings()
- const { selectedNetworks, setSelectedNetworks } = useSettings()
- const { chains } = useConfig()
-
- const allChains = [
- ...new Set([...chains.map(chain => chain.id), ...(readOnlyNetworks || []), ...displayedAssets.map(asset => asset.chainId)])
- ]
-
- const onClickNetwork = (chainId: number) => {
- if (selectedNetworks.includes(chainId)) {
- if (selectedNetworks.length === 1) {
- return
- }
- setSelectedNetworks(selectedNetworks.filter(id => id !== chainId))
- } else {
- setSelectedNetworks([...selectedNetworks, chainId])
- }
- }
-
- return (
-
-
-
- Networks
-
-
- {allChains.map(chain => {
- return (
-
onClickNetwork(chain)}
- value={chain}
- squareIndicator
- >
-
-
-
- {ChainId[chain]}
-
-
-
- )
- })}
-
-
-
- )
-}
diff --git a/packages/wallet-widget/src/views/Settings/Networks.tsx b/packages/wallet-widget/src/views/Settings/Networks.tsx
new file mode 100644
index 000000000..d2e90ba7a
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/Networks.tsx
@@ -0,0 +1,9 @@
+import { NetworksFilter } from '../../components/Filter/NetworksFilter'
+
+export const SettingsNetworks = () => {
+ return (
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/Preferences.tsx b/packages/wallet-widget/src/views/Settings/Preferences.tsx
new file mode 100644
index 000000000..c7e7c4584
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/Preferences.tsx
@@ -0,0 +1,26 @@
+import { Switch, Text } from '@0xsequence/design-system'
+import { useObservable } from 'micro-observables'
+
+import { ListCardSelect } from '../../components/ListCard/ListCardSelect'
+import { HEADER_HEIGHT } from '../../constants'
+import { useSettings } from '../../hooks'
+
+export const SettingsPreferences = () => {
+ const { hideUnlistedTokensObservable, setHideUnlistedTokens } = useSettings()
+ const hideUnlistedTokens = useObservable(hideUnlistedTokensObservable)
+
+ return (
+
+ }
+ type="custom"
+ onClick={() => setHideUnlistedTokens(!hideUnlistedTokens)}
+ >
+
+ Hide Unlisted Tokens
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/Profiles.tsx b/packages/wallet-widget/src/views/Settings/Profiles.tsx
new file mode 100644
index 000000000..d89664dd6
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/Profiles.tsx
@@ -0,0 +1,9 @@
+import { Text } from '@0xsequence/design-system'
+
+export const SettingsProfiles = () => {
+ return (
+
+ Profiles
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/QrScan.tsx b/packages/wallet-widget/src/views/Settings/QrScan.tsx
new file mode 100644
index 000000000..b01af201d
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/QrScan.tsx
@@ -0,0 +1,94 @@
+import { Button, Card, TabsContent, TabsHeader, TabsRoot, Text, TextInput, useMediaQuery } from '@0xsequence/design-system'
+import { Scanner } from '@yudiel/react-qr-scanner'
+import { ChangeEvent, useState } from 'react'
+
+import { HEADER_HEIGHT } from '../../constants'
+// import { useWalletConnectContext } from '../../contexts/WalletConnect'
+import { useNavigation } from '../../hooks'
+
+export function QrScan() {
+ const isMobile = useMediaQuery('isMobile')
+ const { goBack } = useNavigation()
+ const [signClientUri, setSignClientUri] = useState
('')
+ const [selectedTab, setSelectedTab] = useState<'scan' | 'paste'>('scan')
+ // const { pair } = useWalletConnectContext()
+
+ const handleSignClientUri = async () => {
+ if (signClientUri) {
+ console.log(signClientUri)
+ try {
+ // await pair(signClientUri)
+ } catch (error) {
+ console.error('Error pairing with dapp', error)
+ return
+ }
+ }
+ }
+
+ return (
+
+
+ Connect to a DApp using WalletConnect
+
+
setSelectedTab(value as 'scan' | 'paste')}
+ >
+
+
+
+ {
+ if (result[0].rawValue) {
+ setSignClientUri(result[0].rawValue)
+ }
+ }}
+ styles={{
+ video: {
+ transform: isMobile ? 'scaleX(-1)' : 'scaleX(1)',
+ borderRadius: '10px'
+ }
+ }}
+ />
+
+
+
+ ) => setSignClientUri(ev.target.value)}
+ />
+
+ {
+ goBack()
+ }}
+ />
+ {
+ if (signClientUri) {
+ handleSignClientUri()
+ }
+ }}
+ />
+
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/Wallets.tsx b/packages/wallet-widget/src/views/Settings/Wallets.tsx
new file mode 100644
index 000000000..20d472ca5
--- /dev/null
+++ b/packages/wallet-widget/src/views/Settings/Wallets.tsx
@@ -0,0 +1,125 @@
+import { formatAddress, useOpenConnectModal, useWallets } from '@0xsequence/connect'
+import { cardVariants, cn, Text, Divider, IconButton, CheckmarkIcon, CloseIcon, Spinner } from '@0xsequence/design-system'
+import { useState } from 'react'
+
+import { CopyButton } from '../../components/CopyButton'
+import { MediaIconWrapper } from '../../components/IconWrappers'
+import { ListCardSelect } from '../../components/ListCard/ListCardSelect'
+import { WalletAccountGradient } from '../../components/WalletAccountGradient'
+
+export const SettingsWallets = () => {
+ const { wallets, disconnectWallet } = useWallets()
+ const { setOpenConnectModal } = useOpenConnectModal()
+
+ const [disconnectConfirm, setDisconnectConfirm] = useState(null)
+ const [isUnlinking, setIsUnlinking] = useState(false)
+
+ const onClickAddWallet = () => {
+ setOpenConnectModal(true)
+ }
+
+ const DisconnectButton = ({ label, onClick }: { label: string; onClick: () => void }) => {
+ return (
+
+
+ {label}
+
+
+ )
+ }
+
+ const confrimDisconnectAll = () => {
+ setDisconnectConfirm('All')
+ }
+
+ const confirmDisconnect = (address: string) => {
+ setDisconnectConfirm(address)
+ }
+
+ const handleDisconnect = async () => {
+ setIsUnlinking(true)
+ if (disconnectConfirm === 'All') {
+ wallets.forEach(async wallet => await disconnectWallet(wallet.address))
+ } else {
+ await disconnectWallet(disconnectConfirm || '')
+ }
+ setDisconnectConfirm(null)
+ setIsUnlinking(false)
+ }
+
+ return (
+
+
+ {wallets.length > 1 && (
+
+ ) : disconnectConfirm === 'All' ? (
+
+ handleDisconnect()} />
+ setDisconnectConfirm(null)} />
+
+ ) : (
+
confrimDisconnectAll()} />
+ )
+ }
+ >
+ wallet.address)} size="sm" isAccount />
+
+ All
+
+
+ )}
+ {wallets.map(wallet => (
+
+ ) : disconnectConfirm === wallet.address ? (
+
+ handleDisconnect()} />
+ setDisconnectConfirm(null)} />
+
+ ) : (
+ confirmDisconnect(wallet.address)} />
+ )
+ }
+ >
+
+
+ {formatAddress(wallet.address)}
+
+
+
+ ))}
+
+
+
+
+
+
onClickAddWallet()}
+ >
+
+ Add Wallet
+
+
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Settings/index.ts b/packages/wallet-widget/src/views/Settings/index.ts
index f4da7c858..ef634c3e1 100644
--- a/packages/wallet-widget/src/views/Settings/index.ts
+++ b/packages/wallet-widget/src/views/Settings/index.ts
@@ -1,4 +1,8 @@
export * from './Menu'
-export * from './General'
+export * from './Wallets'
+export * from './Profiles'
+export * from './Apps'
export * from './Currency'
-export * from './Network'
+export * from './Networks'
+export * from './Preferences'
+export * from './QrScan'
diff --git a/packages/wallet-widget/src/views/Swap/CoinInput.tsx b/packages/wallet-widget/src/views/Swap/CoinInput.tsx
new file mode 100644
index 000000000..0156940ab
--- /dev/null
+++ b/packages/wallet-widget/src/views/Swap/CoinInput.tsx
@@ -0,0 +1,81 @@
+import { Button, NumericInput, Text } from '@0xsequence/design-system'
+import { ChangeEvent, useEffect, useState } from 'react'
+import { formatUnits } from 'viem'
+
+import { useSettings } from '../../hooks'
+import { useSwap } from '../../hooks/useSwap'
+import { formatFiatBalance, decimalsToWei } from '../../utils/formatBalance'
+
+export const CoinInput = ({ type, disabled }: { type: 'from' | 'to'; disabled?: boolean }) => {
+ const { toCoin, fromCoin, amount, nonRecentAmount, recentInput, setAmount } = useSwap()
+ const coin = type === 'from' ? fromCoin : toCoin
+
+ const { fiatCurrency } = useSettings()
+
+ const [inputValue, setInputValue] = useState('')
+
+ const fiatBalance = formatFiatBalance(
+ type === recentInput ? amount : nonRecentAmount,
+ coin?.price.value || 0,
+ coin?.contractInfo?.decimals || 18,
+ fiatCurrency.sign
+ )
+
+ useEffect(() => {
+ if (type === recentInput) {
+ if (amount > 0) {
+ setInputValue(formatUnits(BigInt(amount), coin?.contractInfo?.decimals || 18))
+ } else if (Number(inputValue)) {
+ setInputValue('')
+ }
+ } else if (type !== recentInput) {
+ if (nonRecentAmount > 0) {
+ setInputValue(formatUnits(BigInt(nonRecentAmount), coin?.contractInfo?.decimals || 18))
+ } else if (Number(inputValue)) {
+ setInputValue('')
+ }
+ }
+ }, [recentInput, amount, nonRecentAmount])
+
+ const handleChange = (ev: ChangeEvent) => {
+ const { value } = ev.target
+ const changedValue = Number(value)
+ setInputValue(value)
+ setAmount(decimalsToWei(changedValue, coin?.contractInfo?.decimals || 18), type)
+ }
+
+ const handleMax = () => {
+ setAmount(Number(formatUnits(BigInt(coin?.balance || 0), coin?.contractInfo?.decimals || 18)), type)
+ }
+
+ return (
+
+
+ {fiatBalance && (
+
+ ~{fiatBalance}
+
+ )}
+ {type === 'from' && (
+
+ )}
+ >
+ }
+ />
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Swap/CoinSelect.tsx b/packages/wallet-widget/src/views/Swap/CoinSelect.tsx
new file mode 100644
index 000000000..6f41a9e24
--- /dev/null
+++ b/packages/wallet-widget/src/views/Swap/CoinSelect.tsx
@@ -0,0 +1,82 @@
+import { cn, cardVariants, Text, ChevronDownIcon, TokenImage } from '@0xsequence/design-system'
+import { AnimatePresence } from 'motion/react'
+import { useState } from 'react'
+import { useChains } from 'wagmi'
+
+import { CoinRow } from '../../components/SearchLists/TokenList/CoinRow'
+import { SlideupDrawer } from '../../components/Select/SlideupDrawer'
+import { useSettings } from '../../hooks'
+import { useSwap } from '../../hooks/useSwap'
+import { TokenBalanceWithPrice } from '../../utils'
+import { formatTokenInfo } from '../../utils/formatBalance'
+
+export const CoinSelect = ({
+ selectType,
+ coinList,
+ disabled
+}: {
+ selectType: 'from' | 'to'
+ coinList: TokenBalanceWithPrice[]
+ disabled?: boolean
+}) => {
+ const { fromCoin, toCoin, setFromCoin, setToCoin } = useSwap()
+ const { fiatCurrency } = useSettings()
+ const chains = useChains()
+
+ const selectedCoin = selectType === 'from' ? fromCoin : toCoin
+ const setSelectedCoin = selectType === 'from' ? setFromCoin : setToCoin
+
+ const [isSelectorOpen, setIsSelectorOpen] = useState(false)
+
+ const { logo, name, symbol, displayBalance } = formatTokenInfo(selectedCoin, fiatCurrency.sign, chains)
+
+ const handleSelect = (coin: TokenBalanceWithPrice) => {
+ setSelectedCoin(coin)
+ setIsSelectorOpen(false)
+ }
+
+ return (
+
+
setIsSelectorOpen(true)}
+ >
+
+
+ {selectType === 'from' ? 'From' : 'To'}
+
+ {selectedCoin ? (
+
+
+
+
+ {name}
+
+
+ {displayBalance}
+
+
+
+ ) : (
+
+ Select Coin
+
+ )}
+
+
+
+
+
+ {isSelectorOpen && (
+ setIsSelectorOpen(false)}>
+
+ {coinList.map((coin, index) => (
+
+ ))}
+
+
+ )}
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Swap/Swap.tsx b/packages/wallet-widget/src/views/Swap/Swap.tsx
new file mode 100644
index 000000000..b8c1c99a5
--- /dev/null
+++ b/packages/wallet-widget/src/views/Swap/Swap.tsx
@@ -0,0 +1,136 @@
+import { ArrowRightIcon, Card, cardVariants, cn, IconButton, Spinner, Text } from '@0xsequence/design-system'
+import { useGetCoinPrices, useGetExchangeRate, useGetTokenBalancesSummary } from '@0xsequence/hooks'
+import { useEffect } from 'react'
+import { useAccount, useChainId } from 'wagmi'
+
+import { NetworkSelect } from '../../components/Select/NetworkSelect'
+import { HEADER_HEIGHT_WITH_LABEL } from '../../constants'
+import { useSettings } from '../../hooks'
+import { useSwap } from '../../hooks/useSwap'
+
+import { CoinInput } from './CoinInput'
+import { CoinSelect } from './CoinSelect'
+
+export const Swap = () => {
+ const {
+ fromCoin,
+ toCoin,
+ isSwapReady,
+ isSwapQuotePending,
+ hasInsufficientFunds,
+ isErrorSwapQuote,
+ isTxnPending,
+ switchCoinOrder,
+ onSubmitSwap,
+ resetSwapStates
+ } = useSwap()
+ const { fiatCurrency } = useSettings()
+ const { address: userAddress } = useAccount()
+ const connectedChainId = useChainId()
+
+ useEffect(() => {
+ return resetSwapStates()
+ }, [])
+
+ const { data: tokenBalances } = useGetTokenBalancesSummary({
+ chainIds: [connectedChainId],
+ filter: {
+ accountAddresses: [String(userAddress)],
+ omitNativeBalances: false
+ }
+ })
+
+ const coinBalances = tokenBalances?.filter(c => c.contractType !== 'ERC1155' && c.contractType !== 'ERC721') || []
+
+ const { data: coinPrices = [] } = useGetCoinPrices(
+ coinBalances.map(token => ({
+ chainId: token.chainId,
+ contractAddress: token.contractAddress
+ }))
+ )
+
+ const { data: conversionRate = 1 } = useGetExchangeRate(fiatCurrency.symbol)
+
+ const coinBalancesWithPrices = coinBalances.map(balance => {
+ const matchingPrice = coinPrices.find(price => {
+ const isSameChainAndAddress =
+ price.token.chainId === balance.chainId && price.token.contractAddress === balance.contractAddress
+
+ const isTokenIdMatch =
+ price.token.tokenId === balance.tokenID || !(balance.contractType === 'ERC721' || balance.contractType === 'ERC1155')
+
+ return isSameChainAndAddress && isTokenIdMatch
+ })
+
+ const priceValue = (matchingPrice?.price?.value || 0) * conversionRate
+ const priceCurrency = fiatCurrency.symbol
+
+ return {
+ ...balance,
+ price: { value: priceValue, currency: priceCurrency }
+ }
+ })
+
+ return (
+
+
+
+
+
+ {fromCoin && }
+ {/* TODO: change out disabled to isTxnPending after new swap api is implemented */}
+ {isErrorSwapQuote &&
+ (hasInsufficientFunds ? (
+
+ Insufficient Funds
+
+ ) : (
+
+ Something went wrong. Try again later or with a different combination of coins.
+
+ ))}
+
+
+
+
+
+ {toCoin && }
+ {isSwapQuotePending && (
+
+
+
+ Fetching best price quote…
+
+
+ )}
+ {isTxnPending && (
+
+
+
+ Sending swap transaction…
+
+
+ )}
+
+
+
+
+ Swap
+
+
+
+ )
+}
diff --git a/packages/wallet-widget/src/views/Swap/index.ts b/packages/wallet-widget/src/views/Swap/index.ts
new file mode 100644
index 000000000..0fba60808
--- /dev/null
+++ b/packages/wallet-widget/src/views/Swap/index.ts
@@ -0,0 +1 @@
+export * from './Swap'
diff --git a/packages/wallet-widget/src/views/SwapCoin/SwapList.tsx b/packages/wallet-widget/src/views/SwapCoin/SwapList.tsx
index 0b4d232fc..235e467f0 100644
--- a/packages/wallet-widget/src/views/SwapCoin/SwapList.tsx
+++ b/packages/wallet-widget/src/views/SwapCoin/SwapList.tsx
@@ -172,7 +172,8 @@ export const SwapList = ({ chainId, contractAddress, amount }: SwapListProps) =>
location: 'coin-details',
params: {
chainId,
- contractAddress
+ contractAddress,
+ accountAddress: userAddress
}
})
} catch (e) {
diff --git a/packages/wallet-widget/src/views/TransactionDetails/index.tsx b/packages/wallet-widget/src/views/TransactionDetails/index.tsx
index e8cdf4e74..d36c0eafa 100644
--- a/packages/wallet-widget/src/views/TransactionDetails/index.tsx
+++ b/packages/wallet-widget/src/views/TransactionDetails/index.tsx
@@ -12,7 +12,7 @@ import {
TokenImage
} from '@0xsequence/design-system'
import { useGetCoinPrices, useGetCollectiblePrices, useGetExchangeRate } from '@0xsequence/hooks'
-import { Transaction, TxnTransfer } from '@0xsequence/indexer'
+import { Transaction, TxnTransfer, TxnTransferType } from '@0xsequence/indexer'
import dayjs from 'dayjs'
import { formatUnits, zeroAddress } from 'viem'
import { useConfig } from 'wagmi'
@@ -91,8 +91,91 @@ export const TransactionDetails = ({ transaction }: TransactionDetailProps) => {
const recipientAddressFormatted =
recipientAddress.substring(0, 10) + '...' + recipientAddress.substring(transfer.to.length - 4, transfer.to.length)
const isNativeToken = compareAddress(transfer?.contractInfo?.address || '', zeroAddress)
- const logoURI = isNativeToken ? nativeTokenInfo.logoURI : transfer?.contractInfo?.logoURI
- const symbol = isNativeToken ? nativeTokenInfo.symbol : transfer?.contractInfo?.symbol || ''
+ const isCollectible = transfer.contractType === 'ERC721' || transfer.contractType === 'ERC1155'
+ const tokenId = transfer.tokenIds?.[0]
+ const tokenLogoURI = isNativeToken
+ ? nativeTokenInfo.logoURI
+ : isCollectible
+ ? transfer?.tokenMetadata?.[String(tokenId)]?.image
+ : transfer?.contractInfo?.logoURI
+ const contractLogoURI = transfer?.contractInfo?.logoURI
+ const tokenSymbol = isNativeToken
+ ? nativeTokenInfo.symbol
+ : isCollectible
+ ? transfer?.tokenMetadata?.[String(tokenId)]?.name || ''
+ : transfer?.contractInfo?.symbol || ''
+ const contractSymbol = transfer?.contractInfo?.name || ''
+
+ const WalletContent = () => (
+
+
+
+ {recipientAddressFormatted}
+
+
+ )
+
+ const TokenContent = ({
+ balanceDisplayed,
+ fiatValue,
+ fiatPrice
+ }: {
+ balanceDisplayed: string
+ fiatValue: string
+ fiatPrice: number
+ }) => (
+
+ {isCollectible && (
+
+
+
+ {contractSymbol}
+
+
+ )}
+
+
+
+
+ {`${balanceDisplayed} ${tokenSymbol}`}
+
+ {arePricesLoading ? (
+
+ ) : (
+
+ {fiatPrice ? `${fiatCurrency.sign}${fiatValue}` : ''}
+
+ )}
+
+
+
+ )
return (
<>
@@ -119,36 +202,23 @@ export const TransactionDetails = ({ transaction }: TransactionDetailProps) => {
const fiatValue = (parseFloat(formattedBalance) * (conversionRate * (fiatPrice || 0))).toFixed(2)
+ const isReceiveTransfer = transfer.transferType === TxnTransferType.RECEIVE
+
return (
-
-
-
-
- {`${balanceDisplayed} ${symbol}`}
-
- {arePricesLoading ? (
-
- ) : (
-
- {fiatPrice ? `${fiatCurrency.sign}${fiatValue}` : ''}
-
- )}
-
-
-
-
-
-
- {recipientAddressFormatted}
-
-
+ {isReceiveTransfer ? (
+ <>
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+ >
+ )}
)
})}
diff --git a/packages/wallet-widget/src/views/index.ts b/packages/wallet-widget/src/views/index.ts
index c300c9c9b..afb06a806 100644
--- a/packages/wallet-widget/src/views/index.ts
+++ b/packages/wallet-widget/src/views/index.ts
@@ -1,13 +1,12 @@
export * from './Home'
export * from './Receive'
-export * from './SendCoin'
-export * from './SendCollectible'
+export * from './Send'
export * from './History'
export * from './Search'
export * from './Settings'
export * from './CoinDetails'
-export * from './CollectionDetails'
export * from './CollectibleDetails'
export * from './TransactionDetails'
export * from './SwapCoin'
export * from './SwapCoin/SwapList'
+export * from './Swap/Swap'
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 582778d78..6856c614a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -82,7 +82,7 @@ importers:
version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(motion@12.4.10(@emotion/is-prop-valid@0.8.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@0xsequence/network':
specifier: '*'
- version: 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
+ version: 2.3.9(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
'@radix-ui/react-popover':
specifier: ^1.0.7
version: 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -546,6 +546,9 @@ importers:
fuse.js:
specifier: ^6.6.2
version: 6.6.2
+ micro-observables:
+ specifier: 1.7.2
+ version: 1.7.2(react@19.0.0)
motion:
specifier: ^12.3.1
version: 12.4.10(@emotion/is-prop-valid@0.8.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -556,6 +559,9 @@ importers:
specifier: ^5.1.0
version: 5.1.0(react@19.0.0)
devDependencies:
+ '@0xsequence/checkout':
+ specifier: workspace:*
+ version: link:../checkout
'@0xsequence/connect':
specifier: workspace:*
version: link:../connect
@@ -565,6 +571,9 @@ importers:
'@types/react-copy-to-clipboard':
specifier: ^5.0.7
version: 5.0.7
+ '@yudiel/react-qr-scanner':
+ specifier: 2.2.1
+ version: 2.2.1(@types/emscripten@1.40.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
ethers:
specifier: ^6.13.0
version: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
@@ -588,9 +597,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/abi@2.2.13':
- resolution: {integrity: sha512-cZDR83SNxpXTD9vZoJAtmn6/YgvttN0gmeB8feQ5cpo8yd+AeJvQpUGMPR6Ud1MQGsvcPTLnTwKkL432Pc6UGQ==}
-
'@0xsequence/abi@2.3.9':
resolution: {integrity: sha512-5bFZIerqx4VMxny5PdFAGH4uyZhzvsH3Ri1/U0Tr2a05t5jSSXM5YVCf8QzWpSS51lpPRknMrvuuBUfEcV2dgw==}
@@ -607,11 +613,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/core@2.2.13':
- resolution: {integrity: sha512-tu6OEGbDLg1KfMb+YOn0Z5BsYbK3UFBjuPVHRx7SpmCsZPEApJqqRKHpTYah2T3bmYIJy9tRBtqstfTsniSgng==}
- peerDependencies:
- ethers: '>=6'
-
'@0xsequence/core@2.3.9':
resolution: {integrity: sha512-N97jPBe//72upmkelaypiSRLhGzVIHttOxRGa2w8b3lH6lNJ6tVHYkcrCU3I8GCnnURyINbVYR+r2C2s0+2sYQ==}
peerDependencies:
@@ -634,9 +635,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/indexer@2.2.13':
- resolution: {integrity: sha512-RFjjjckuAhM0vgYFO1RgYyBqsUrU54l2N/Isr5DPSLCCczp+qcopNuFMB0e0FuvzUP1buunxTjHRVjFH75kQEA==}
-
'@0xsequence/indexer@2.3.9':
resolution: {integrity: sha512-ZtiA7827BTjujOupom5dGJd4oMvfQA2HQ9orjrreZusQPmfadie9ldVrnzX19YS+AZDeCOix9qDG+cRSpYfHwQ==}
@@ -651,11 +649,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/network@2.2.13':
- resolution: {integrity: sha512-U8sVC2nWokPtQzIXwNKOP/mgkkuvjxYmQrgITkc8YDTAQOYPu6n/4lIqQ2//jjSfloniMK00tDpfUd5fCFbsUA==}
- peerDependencies:
- ethers: '>=6'
-
'@0xsequence/network@2.3.9':
resolution: {integrity: sha512-QFvGsfkjkuENI3yrBAil1Axm0iBK/BMO8nqEo5MZ8zxYPkOG3I4Lyjr28s4Ny2aOUzaV8I3R4udTOM+S6b5vXw==}
peerDependencies:
@@ -666,11 +659,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/relayer@2.2.13':
- resolution: {integrity: sha512-fnt4AJ1u9CPwx7JJwpZ7UbJ3eN2LOG0Wuwe4FS9OSfxCOhbokELRSWegToEyH6ew6FRPvsuRMN/im3Bu3Og0QQ==}
- peerDependencies:
- ethers: '>=6'
-
'@0xsequence/relayer@2.3.9':
resolution: {integrity: sha512-Ta9vYWfl38nNj1HVgf8igjH41oj5aY+ZK923Rio1ms5D4WWR6oSoHBBFRmbU5qT8HzTa8GWoYrxhohHcPV5S6g==}
peerDependencies:
@@ -691,11 +679,6 @@ packages:
peerDependencies:
ethers: '>=6'
- '@0xsequence/utils@2.2.13':
- resolution: {integrity: sha512-V4uip1fCZAzp5O2S+nkKnwrqmzzC7em1Mc4HJvUX+fqT0jzw20BZt0CNlX34DgW6E6MzBvWnrX+DTfz/+alBWQ==}
- peerDependencies:
- ethers: '>=6'
-
'@0xsequence/utils@2.3.9':
resolution: {integrity: sha512-dZI3dWkHABkRj39fp+GdieadQiXzntosrClwYKf7wT780/e6DlBMZV2tb/iI+j73Qq64+MfSheimEw7Tjk+kww==}
peerDependencies:
@@ -3431,6 +3414,9 @@ packages:
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ '@types/emscripten@1.40.0':
+ resolution: {integrity: sha512-MD2JJ25S4tnjnhjWyalMS6K6p0h+zQV6+Ylm+aGbiS8tSn/aHLSGNzBgduj6FB4zH0ax2GRMGYi/8G1uOxhXWA==}
+
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
@@ -3771,6 +3757,12 @@ packages:
'@walletconnect/window-metadata@1.0.1':
resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==}
+ '@yudiel/react-qr-scanner@2.2.1':
+ resolution: {integrity: sha512-5tmzoi9d8mqqaxKTxfI9kulS3N3Kph75AOqwU2lnl4IMwjmLcTXS8IyecDUvzFNuoMNhCpofrqqGueXm8IXkjA==}
+ peerDependencies:
+ react: ^17 || ^18 || ^19
+ react-dom: ^17 || ^18 || ^19
+
abitype@1.0.8:
resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==}
peerDependencies:
@@ -3959,6 +3951,9 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ barcode-detector@3.0.1:
+ resolution: {integrity: sha512-3fCzG/Py4SVgZJhubD1mt7rVprtHEVWrxQN4FUOG0oulPE4193evbgyptxcOYsfTNEtMlWc+Ec9tdxhjlR4/Ww==}
+
base-x@3.0.11:
resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==}
@@ -5232,6 +5227,9 @@ packages:
hmac-drbg@1.0.1:
resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==}
+ hoist-non-react-statics@3.3.2:
+ resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
+
html-encoding-sniffer@4.0.0:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
@@ -5846,6 +5844,12 @@ packages:
micro-ftch@0.3.1:
resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==}
+ micro-observables@1.7.2:
+ resolution: {integrity: sha512-NLXMvBpeXO/QAJ9r2SoxAE9qJXvECMRnKXkQrjZ5TNy0bUKawrgyUafHbJpFnP3j+DTehjPxJU6VXnNMjvicNA==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ react: '>=16.8.0'
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -6745,6 +6749,9 @@ packages:
scrypt-js@3.0.1:
resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==}
+ sdp@3.2.0:
+ resolution: {integrity: sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==}
+
secp256k1@4.0.4:
resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==}
engines: {node: '>=18.0.0'}
@@ -7724,6 +7731,10 @@ packages:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}
+ webrtc-adapter@9.0.1:
+ resolution: {integrity: sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==}
+ engines: {node: '>=6.0.0', npm: '>=3.10.0'}
+
websocket@1.0.35:
resolution: {integrity: sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==}
engines: {node: '>=4.0.0'}
@@ -7958,6 +7969,11 @@ packages:
use-sync-external-store:
optional: true
+ zxing-wasm@2.1.0:
+ resolution: {integrity: sha512-CvuwDZHRHwg6PeCARaCDIp3dauD4cin0mbHrQQZtMDrr5mblPzCimAjdw/XMhD/Au10q/f5+SAupvYqYvUOg1Q==}
+ peerDependencies:
+ '@types/emscripten': '>=1.39.6'
+
snapshots:
0xsequence@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)):
@@ -7980,8 +7996,6 @@ snapshots:
'@0xsequence/wallet': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- '@0xsequence/abi@2.2.13': {}
-
'@0xsequence/abi@2.3.9': {}
'@0xsequence/account@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
@@ -8015,12 +8029,6 @@ snapshots:
'@0xsequence/wallet': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- '@0xsequence/core@2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
- dependencies:
- '@0xsequence/abi': 2.2.13
- '@0xsequence/utils': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- ethers: 6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10)
-
'@0xsequence/core@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
dependencies:
'@0xsequence/abi': 2.3.9
@@ -8073,8 +8081,6 @@ snapshots:
'@0xsequence/utils': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- '@0xsequence/indexer@2.2.13': {}
-
'@0xsequence/indexer@2.3.9': {}
'@0xsequence/marketplace@2.2.7': {}
@@ -8088,14 +8094,6 @@ snapshots:
'@0xsequence/wallet': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- '@0xsequence/network@2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
- dependencies:
- '@0xsequence/core': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- '@0xsequence/indexer': 2.2.13
- '@0xsequence/relayer': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- '@0xsequence/utils': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- ethers: 6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10)
-
'@0xsequence/network@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
dependencies:
'@0xsequence/core': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
@@ -8128,13 +8126,6 @@ snapshots:
eventemitter2: 6.4.9
webextension-polyfill: 0.10.0
- '@0xsequence/relayer@2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
- dependencies:
- '@0xsequence/abi': 2.2.13
- '@0xsequence/core': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- '@0xsequence/utils': 2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
- ethers: 6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10)
-
'@0xsequence/relayer@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
dependencies:
'@0xsequence/abi': 2.3.9
@@ -8169,11 +8160,6 @@ snapshots:
'@0xsequence/core': 2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- '@0xsequence/utils@2.2.13(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
- dependencies:
- ethers: 6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10)
- js-base64: 3.7.7
-
'@0xsequence/utils@2.3.9(ethers@6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
dependencies:
ethers: 6.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
@@ -9581,7 +9567,7 @@ snapshots:
'@imtbl/passport@2.1.15(bufferutil@4.0.9)(utf-8-validate@5.0.10)':
dependencies:
- '@0xsequence/abi': 2.2.13
+ '@0xsequence/abi': 2.3.9
'@0xsequence/core': 2.3.9(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))
'@imtbl/config': 2.1.15
'@imtbl/generated-clients': 2.1.15
@@ -11642,6 +11628,8 @@ snapshots:
dependencies:
'@types/ms': 2.1.0
+ '@types/emscripten@1.40.0': {}
+
'@types/estree@1.0.6': {}
'@types/graceful-fs@4.1.9':
@@ -12500,6 +12488,15 @@ snapshots:
'@walletconnect/window-getters': 1.0.1
tslib: 1.14.1
+ '@yudiel/react-qr-scanner@2.2.1(@types/emscripten@1.40.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ barcode-detector: 3.0.1(@types/emscripten@1.40.0)
+ react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
+ webrtc-adapter: 9.0.1
+ transitivePeerDependencies:
+ - '@types/emscripten'
+
abitype@1.0.8(typescript@5.8.2):
optionalDependencies:
typescript: 5.8.2
@@ -12722,6 +12719,12 @@ snapshots:
balanced-match@1.0.2: {}
+ barcode-detector@3.0.1(@types/emscripten@1.40.0):
+ dependencies:
+ zxing-wasm: 2.1.0(@types/emscripten@1.40.0)
+ transitivePeerDependencies:
+ - '@types/emscripten'
+
base-x@3.0.11:
dependencies:
safe-buffer: 5.2.1
@@ -14414,6 +14417,10 @@ snapshots:
minimalistic-assert: 1.0.1
minimalistic-crypto-utils: 1.0.1
+ hoist-non-react-statics@3.3.2:
+ dependencies:
+ react-is: 16.13.1
+
html-encoding-sniffer@4.0.0:
dependencies:
whatwg-encoding: 3.1.1
@@ -15079,6 +15086,11 @@ snapshots:
micro-ftch@0.3.1: {}
+ micro-observables@1.7.2(react@19.0.0):
+ dependencies:
+ hoist-non-react-statics: 3.3.2
+ react: 19.0.0
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -16067,6 +16079,8 @@ snapshots:
scrypt-js@3.0.1: {}
+ sdp@3.2.0: {}
+
secp256k1@4.0.4:
dependencies:
elliptic: 6.6.1
@@ -17102,6 +17116,10 @@ snapshots:
webidl-conversions@7.0.0: {}
+ webrtc-adapter@9.0.1:
+ dependencies:
+ sdp: 3.2.0
+
websocket@1.0.35:
dependencies:
bufferutil: 4.0.9
@@ -17344,3 +17362,8 @@ snapshots:
'@types/react': 19.0.10
react: 19.0.0
use-sync-external-store: 1.4.0(react@19.0.0)
+
+ zxing-wasm@2.1.0(@types/emscripten@1.40.0):
+ dependencies:
+ '@types/emscripten': 1.40.0
+ type-fest: 4.37.0