ci(release): publish latest release

parent 4df1f115
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `QmX4W6sgCHYCcR4SxeJVbZnj5N1GXR2ERPJomoBjVSbZVZ` - CIDv0: `QmSyV4dNhjeqsxaKHkFZyqyLKGaqBUkgr5fb1FDZN24yY5`
- CIDv1: `bafybeiebsyucxoiaieyyktifwl7glbepaklj4tncplc3rvssq55rpl553a` - CIDv1: `bafybeice3zkknbq42szpbonaebytodvjc7rddzz3v5rc4hd6wjts6t2usi`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
...@@ -10,118 +10,21 @@ You can also access the Uniswap Interface from an IPFS gateway. ...@@ -10,118 +10,21 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs. Your Uniswap settings are never remembered across different URLs.
IPFS gateways: IPFS gateways:
- https://bafybeiebsyucxoiaieyyktifwl7glbepaklj4tncplc3rvssq55rpl553a.ipfs.dweb.link/ - https://bafybeice3zkknbq42szpbonaebytodvjc7rddzz3v5rc4hd6wjts6t2usi.ipfs.dweb.link/
- https://bafybeiebsyucxoiaieyyktifwl7glbepaklj4tncplc3rvssq55rpl553a.ipfs.cf-ipfs.com/ - https://bafybeice3zkknbq42szpbonaebytodvjc7rddzz3v5rc4hd6wjts6t2usi.ipfs.cf-ipfs.com/
- [ipfs://QmX4W6sgCHYCcR4SxeJVbZnj5N1GXR2ERPJomoBjVSbZVZ/](ipfs://QmX4W6sgCHYCcR4SxeJVbZnj5N1GXR2ERPJomoBjVSbZVZ/) - [ipfs://QmSyV4dNhjeqsxaKHkFZyqyLKGaqBUkgr5fb1FDZN24yY5/](ipfs://QmSyV4dNhjeqsxaKHkFZyqyLKGaqBUkgr5fb1FDZN24yY5/)
## 5.13.0 (2024-02-27) ## 5.14.0 (2024-02-27)
### Features ### Features
* **web:** [info] Add Bottom Bar to PDP mWeb (#6444) edd221d * **web:** add disclaimer to limits review modal (#6597) f1cb196
* **web:** [info] add tvl and volume % change to PDP query (#6453) 3054897
* **web:** [info] add warning label to swap modal on PDP page (#6398) f7bacf9
* **web:** [info] candlestick data integration and fallback refactor (#6510) 1136e54
* **web:** [info] candlestick tooltip (#6355) fbb184f
* **web:** [info] Connect PDP data to our BE (#6357) 45a32d6
* **web:** [info] Connect PDP Volume Chart to real data (#6455) 3c7fa86
* **web:** [info] Integrate BE Pool TX queries (#6424) d2df578
* **web:** [info] Migrate Explore and TDP TX tables to our GQL BE (#6502) b674b85
* **web:** [info] pdp loading states (#6504) 57c0279
* **web:** [info] Sortable Token Explore Table Headers (#6435) f0e95d0
* **web:** [info] TDP chart loading states (#6450) d45a2e7
* **web:** [info] use custom PDP seo page title (#6422) f2e6552
* **web:** [info] use dropdown bottom sheet in smaller screens (#6452) 0177aaa
* **web:** [info] Use real price data for PDP Price Chart (#6457) 9493135
* **web:** [info] Various mWeb polish (#6549) 97e313e
* **web:** [uni-tags] adding username to send (#6358) 507bffc
* **web:** [uni-tags] improve Web3Status and account drawer header (#6454) 0c57325
* **web:** [uni-tags] update banner copy and responsive styles (#6401) b8445de
* **web:** add Explore and TDP chart staleness checks (#6458) 71cac56
* **web:** add gas estimate to limits dialog (#6233) 6689ae4
* **web:** add more analytics for limits (#6475) 14de73d
* **web:** Add more limits analytics events (#6496) 1bc5245
* **web:** Add off chain order type to trade events and swap tab click event (#6417) 3ad9ce0
* **web:** add price change speedbump to limit form (#6447) 1f855b5
* **web:** change input currency from LimitPriceInputPanel (#6250) 8313cb9
* **web:** fix limit status updating (#6363) 727de8b
* **web:** handle remote open limits (#6407) 519dbb9
* **web:** invert limit price preset button adjustments (#6518) c93f355
* **web:** mv limits cta to activity tab (#6532) e34eb1c
* **web:** pending states for cancelling limits (#6360) 1a3f5b9
* **web:** redesign limits menu rows (#6575) 11ac692
* **web:** Set default quote currency in limits price display based on stablecoin (#6456) 4b5a48a
* **web:** sync url to swap tab (#6432) ffb2d8c
* **web:** transaction details for insufficient liquidity (#6531) 8d85c98
* **web:** Update progress indicator step titles for limit orders (#6470) 090248e
* **web:** update TOS last updated to 2/16/2024 (#6550) 533b087
* **web:** Use GQL Token Data for Pool Token Logos (#6505) 00e6504
### Bug Fixes ### Bug Fixes
* **web:** [info] add tooltip for turnover on token table (#6507) 50ea4f5 * **web:** fix expiry line item (#6596) 7225ae9
* **web:** [info] block explorer icon not showing dark mode TDP (#6557) f0ca33d * **web:** use page chain for liquidity chart (#6582) 4e89b28
* **web:** [info] explore table mobile hover (#6512) 7abb6f7
* **web:** [info] fix extralong numbers on explore chart section (#6524) db5bbdc
* **web:** [info] fix translations for chart type selector (#6533) ee54af9
* **web:** [info] flickering volume bars (#6581) 60582ac
* **web:** [info] hide chart y-axis on smaller screen (#6506) c64a8f4
* **web:** [info] knock out a bunch of high-pri polish tasks (#6305) e5d0797
* **web:** [info] make return to top clickable again (#6559) 6d65932
* **web:** [info] MOOREE polish (#6486) 0a5b22f
* **web:** [info] more polish (#6434) 41ca7ea
* **web:** [info] pdp matching tdp (#6501) fb8ec9d
* **web:** [info] Prevent infinite loading for fully loaded tables (#6394) 4233a2f
* **web:** [info] pull decimal data for gql tokens (#6558) 3d9a336
* **web:** [info] Show explorer icon in PDP Links in darkmode (#6584) 8bd04e5
* **web:** [info] Show PDP balances on mWeb (#6585) aee363f
* **web:** [info] Show TDP Bottom Bar at exactly 1024px (#6576) d04dd12
* **web:** [limits] empty transaction details with ETH (#6519) 8c1532d
* **web:** [limits] fix transaction details text to match design (#6534) dc4dbd3
* **web:** [limits] making market button the same as percentage (#6516) 6f417c9
* **web:** [limits] update order confirmation flow (#6490) 0966070
* **web:** [uni-tags] inline banner height, icon size, pfp (#6538) 67b10ab
* **web:** align swap box and action buttons (#6497) 7c846bc
* **web:** chain switching search params (#6491) 6c88199
* **web:** chain switching search params (#6491) (#6514) f10d64e
* **web:** Change auction period secs to 0 (#6589) eab18eb
* **web:** clear limits form when submitting a limit (#6515) 9bab70b
* **web:** color code buy/sell on TDP tx table (#6498) eaafcb6
* **web:** convert backend timestamp from sec to ms for X orders (#6540) 4161221
* **web:** de-crowd the swap header bar (#6546) b0fd755
* **web:** disable test and update gql schema (#6517) e3aa751
* **web:** disable text select on the $ in the send form (#6433) 2a9ba50
* **web:** division by zero error in limits menu (#6561) 3190502
* **web:** do not truncate token symbols (#6495) 3f3b28b
* **web:** enable limits for all tokens (#6485) ee6fd22
* **web:** fix cancelation confirmation modal for limit orders (#6583) 8565065
* **web:** fix limit tab breaking after switching to l2s (#6554) 15f2d32
* **web:** ignore touchmove on charts (#6500) 51c7d32
* **web:** invert displayed custom price adjustment to match presets (#6560) a9fbe5c
* **web:** layout bug in token selector (#6484) a4e2de1
* **web:** limit form styling nits (#6253) ca34460
* **web:** limiting max decimals in input (#6446) df01d65
* **web:** limits menu styling nits (#6254) a83faa5
* **web:** lint error in useCurrentPriceAdjustment (#6492) cd1e011
* **web:** long pool name overlap (#6503) 78d4d8c
* **web:** minor design nits for limits (#6522) 450366a
* **web:** Misc. design fixes to Token Detail Page (#6565) 7146990
* **web:** open limits menu button bug (#6389) 7cdcc98
* **web:** revert - clear limits form when submitting a limit (#6515) (#6528) 52ef6fd
* **web:** setState error from LimitForm (#6249) df2aca3
* **web:** stacked tvl rendering overlap (#6573) f090a13
* **web:** styling fixes for limits flow (#6525) 72ed86b
* **web:** swap header<>url navigation bug (#6513) ad8d8d9
* **web:** swap z-indexing (#6499) 1573567
* **web:** truncate currency amount to decimals when parsing (#6586) 2a891d9
* **web:** Use local activities if GraphQL assetActivities query returns nothing (#6494) 137b253
### Code Refactoring
* **web:** [info] tdp provider pattern (#6385) 5c52db7
* **web:** [info] use tdp context in subcomponents (#6400) 99bbedc
web/5.13.0 web/5.14.0
\ No newline at end of file \ No newline at end of file
...@@ -57,6 +57,7 @@ import { ...@@ -57,6 +57,7 @@ import {
v55Schema, v55Schema,
v56Schema, v56Schema,
v57Schema, v57Schema,
v58Schema,
v5Schema, v5Schema,
v6Schema, v6Schema,
v7Schema, v7Schema,
...@@ -1299,4 +1300,11 @@ describe('Redux state migrations', () => { ...@@ -1299,4 +1300,11 @@ describe('Redux state migrations', () => {
expect(v58.behaviorHistory.hasSkippedUnitagPrompt).toBe(false) expect(v58.behaviorHistory.hasSkippedUnitagPrompt).toBe(false)
}) })
it('migrates from v58 to 59', () => {
const v58Stub = { ...v58Schema }
const v59 = migrations[59](v58Stub)
expect(v59.behaviorHistory.hasCompletedUnitagsIntroModal).toBe(false)
})
}) })
...@@ -793,4 +793,15 @@ export const migrations = { ...@@ -793,4 +793,15 @@ export const migrations = {
return newState return newState
}, },
59: function addCompletedUnitagsIntroBoolean(state: any) {
const newState = { ...state }
newState.behaviorHistory = {
...state.behaviorHistory,
hasCompletedUnitagsIntroModal: false,
}
return newState
},
} }
...@@ -287,6 +287,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -287,6 +287,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
horizontalGap="$spacing8" horizontalGap="$spacing8"
showViewOnlyBadge={isViewOnly} showViewOnlyBadge={isViewOnly}
size={spacing.spacing60 - spacing.spacing4} size={spacing.spacing60 - spacing.spacing4}
variant="subheading1"
/> />
<Flex px="$spacing24"> <Flex px="$spacing24">
<Button <Button
......
...@@ -243,6 +243,7 @@ exports[`AccountSwitcher renders correctly 1`] = ` ...@@ -243,6 +243,7 @@ exports[`AccountSwitcher renders correctly 1`] = `
{ {
"alignItems": "center", "alignItems": "center",
"flexDirection": "row", "flexDirection": "row",
"gap": 4,
"justifyContent": "center", "justifyContent": "center",
} }
} }
......
...@@ -435,6 +435,13 @@ export const v58Schema = { ...@@ -435,6 +435,13 @@ export const v58Schema = {
}, },
} }
export const v59Schema = {
...v58Schema,
behaviorHistory: {
...v58Schema.behaviorHistory,
hasCompletedUnitagsIntroModal: false,
},
}
// TODO: [MOB-201] use function with typed output when API reducers are removed from rootReducer // TODO: [MOB-201] use function with typed output when API reducers are removed from rootReducer
// export const getSchema = (): RootState => v0Schema // export const getSchema = (): RootState => v0Schema
export const getSchema = (): typeof v57Schema => v57Schema export const getSchema = (): typeof v57Schema => v57Schema
...@@ -75,7 +75,7 @@ export const persistConfig = { ...@@ -75,7 +75,7 @@ export const persistConfig = {
key: 'root', key: 'root',
storage: reduxStorage, storage: reduxStorage,
whitelist, whitelist,
version: 58, version: 59,
migrate: createMigrate(migrations), migrate: createMigrate(migrations),
} }
......
...@@ -154,6 +154,10 @@ function getMetamaskAddress(uri: string): Nullable<string> { ...@@ -154,6 +154,10 @@ function getMetamaskAddress(uri: string): Nullable<string> {
// format is scantastic://<uri> // format is scantastic://<uri>
function getScantasticAddress(uri: string): Nullable<string> { function getScantasticAddress(uri: string): Nullable<string> {
if (!uri.startsWith('scantastic://')) {
return null
}
const uriParts = uri.split('://') const uriParts = uri.split('://')
if (uriParts.length < 2) { if (uriParts.length < 2) {
......
...@@ -386,6 +386,7 @@ exports[`AccountList renders without error 1`] = ` ...@@ -386,6 +386,7 @@ exports[`AccountList renders without error 1`] = `
{ {
"alignItems": "center", "alignItems": "center",
"flexDirection": "row", "flexDirection": "row",
"gap": 4,
"justifyContent": "center", "justifyContent": "center",
} }
} }
......
...@@ -127,7 +127,7 @@ const ChoosePhotoOption = ({ type }: { type: PhotoAction }): JSX.Element => { ...@@ -127,7 +127,7 @@ const ChoosePhotoOption = ({ type }: { type: PhotoAction }): JSX.Element => {
<Text <Text
color={type === PhotoAction.RemovePhoto ? '$statusCritical' : '$neutral1'} color={type === PhotoAction.RemovePhoto ? '$statusCritical' : '$neutral1'}
numberOfLines={1} numberOfLines={1}
variant="body1"> variant="buttonLabel2">
{type === PhotoAction.BrowseCameraRoll && t('Choose from camera roll')} {type === PhotoAction.BrowseCameraRoll && t('Choose from camera roll')}
{type === PhotoAction.BrowseNftsList && t('Choose an NFT')} {type === PhotoAction.BrowseNftsList && t('Choose an NFT')}
{type === PhotoAction.RemovePhoto && t('Remove profile picture')} {type === PhotoAction.RemovePhoto && t('Remove profile picture')}
......
...@@ -2,8 +2,9 @@ import React from 'react' ...@@ -2,8 +2,9 @@ import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard, StyleProp, ViewStyle } from 'react-native' import { Keyboard, StyleProp, ViewStyle } from 'react-native'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { navigate } from 'src/app/navigation/rootNavigation'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { Screens } from 'src/screens/Screens' import { Screens, UnitagScreens } from 'src/screens/Screens'
import { import {
Flex, Flex,
Image, Image,
...@@ -15,8 +16,10 @@ import { ...@@ -15,8 +16,10 @@ import {
} from 'ui/src' } from 'ui/src'
import { UNITAGS_BANNER_VERTICAL_DARK, UNITAGS_BANNER_VERTICAL_LIGHT } from 'ui/src/assets' import { UNITAGS_BANNER_VERTICAL_DARK, UNITAGS_BANNER_VERTICAL_LIGHT } from 'ui/src/assets'
import { borderRadii, iconSizes, spacing } from 'ui/src/theme' import { borderRadii, iconSizes, spacing } from 'ui/src/theme'
import { selectHasCompletedUnitagsIntroModal } from 'wallet/src/features/behaviorHistory/selectors'
import { setHasSkippedUnitagPrompt } from 'wallet/src/features/behaviorHistory/slice' import { setHasSkippedUnitagPrompt } from 'wallet/src/features/behaviorHistory/slice'
import { UNITAG_SUFFIX_NO_LEADING_DOT } from 'wallet/src/features/unitags/constants' import { UNITAG_SUFFIX_NO_LEADING_DOT } from 'wallet/src/features/unitags/constants'
import { useAppSelector } from 'wallet/src/state'
import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry' import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry'
import { ElementName, ModalName, UnitagEventName } from 'wallet/src/telemetry/constants' import { ElementName, ModalName, UnitagEventName } from 'wallet/src/telemetry/constants'
...@@ -38,6 +41,8 @@ export function UnitagBanner({ ...@@ -38,6 +41,8 @@ export function UnitagBanner({
const { fullWidth } = useDeviceDimensions() const { fullWidth } = useDeviceDimensions()
const isDarkMode = useIsDarkMode() const isDarkMode = useIsDarkMode()
const colors = useSporeColors() const colors = useSporeColors()
const hasCompletedUnitagsIntroModal = useAppSelector(selectHasCompletedUnitagsIntroModal)
const imageWidth = compact const imageWidth = compact
? COMPACT_IMAGE_SCREEN_WIDTH_PROPORTION * fullWidth ? COMPACT_IMAGE_SCREEN_WIDTH_PROPORTION * fullWidth
: IMAGE_SCREEN_WIDTH_PROPORTION * fullWidth : IMAGE_SCREEN_WIDTH_PROPORTION * fullWidth
...@@ -50,8 +55,19 @@ export function UnitagBanner({ ...@@ -50,8 +55,19 @@ export function UnitagBanner({
action: 'claim', action: 'claim',
entryPoint: analyticsEntryPoint, entryPoint: analyticsEntryPoint,
}) })
if (hasCompletedUnitagsIntroModal) {
navigate(Screens.UnitagStack, {
screen: UnitagScreens.ClaimUnitag,
params: {
entryPoint,
address,
},
})
} else {
dispatch(openModal({ name: ModalName.UnitagsIntro, initialState: { address, entryPoint } })) dispatch(openModal({ name: ModalName.UnitagsIntro, initialState: { address, entryPoint } }))
} }
}
const onPressMaybeLater = (): void => { const onPressMaybeLater = (): void => {
sendWalletAnalyticsEvent(UnitagEventName.UnitagBannerActionTaken, { sendWalletAnalyticsEvent(UnitagEventName.UnitagBannerActionTaken, {
...@@ -77,12 +93,12 @@ export function UnitagBanner({ ...@@ -77,12 +93,12 @@ export function UnitagBanner({
alignContent="space-between" alignContent="space-between"
backgroundColor={compact ? '$surface2' : '$background'} backgroundColor={compact ? '$surface2' : '$background'}
borderColor="$surface3" borderColor="$surface3"
borderRadius="$rounded16" borderRadius="$rounded20"
borderWidth={compact ? undefined : '$spacing1'} borderWidth={compact ? undefined : '$spacing1'}
mt="$spacing12" mt="$spacing12"
overflow="hidden" overflow="hidden"
pl="$spacing16" pl="$spacing16"
py="$spacing16" py="$spacing12"
shadowColor="$neutral3" shadowColor="$neutral3"
shadowOpacity={0.4} shadowOpacity={0.4}
shadowRadius="$spacing4"> shadowRadius="$spacing4">
...@@ -134,7 +150,7 @@ export function UnitagBanner({ ...@@ -134,7 +150,7 @@ export function UnitagBanner({
}} }}
testID={ElementName.Cancel} testID={ElementName.Cancel}
onPress={onPressMaybeLater}> onPress={onPressMaybeLater}>
<Text color="$neutral3" variant="buttonLabel4"> <Text color="$neutral2" variant="buttonLabel4">
{t('Maybe later')} {t('Maybe later')}
</Text> </Text>
</TouchableArea> </TouchableArea>
......
...@@ -22,7 +22,9 @@ export function UnitagProfilePicture({ ...@@ -22,7 +22,9 @@ export function UnitagProfilePicture({
<Flex <Flex
shrink shrink
backgroundColor="$surface1" backgroundColor="$surface1"
borderColor="$surface1"
borderRadius="$roundedFull" borderRadius="$roundedFull"
borderWidth={2}
height={size} height={size}
overflow="hidden" overflow="hidden"
shadowColor="$neutral3" shadowColor="$neutral3"
......
...@@ -24,15 +24,15 @@ export const UnitagWithProfilePicture = ({ ...@@ -24,15 +24,15 @@ export const UnitagWithProfilePicture = ({
backgroundColor="$surface1" backgroundColor="$surface1"
borderRadius="$rounded32" borderRadius="$rounded32"
px="$spacing12" px="$spacing12"
py="$spacing16" py="$spacing8"
shadowColor="$neutral3" shadowColor="$neutral3"
shadowOpacity={0.4} shadowOpacity={0.4}
shadowRadius="$spacing4" shadowRadius="$spacing4"
transform={[{ rotateZ: '-2deg' }]} transform={[{ rotateZ: '-2deg' }]}
zIndex="$popover"> zIndex="$popover">
<Text color="$accent1" variant="buttonLabel1"> <Text color="$accent1" variant="subheading1">
{unitag} {unitag}
<Text color="$neutral2" variant="buttonLabel1"> <Text color="$neutral3" variant="subheading1">
{UNITAG_SUFFIX} {UNITAG_SUFFIX}
</Text> </Text>
</Text> </Text>
......
...@@ -12,6 +12,7 @@ import { Button, Flex, GeneratedIcon, Icons, Image, Text, useIsDarkMode } from ' ...@@ -12,6 +12,7 @@ import { Button, Flex, GeneratedIcon, Icons, Image, Text, useIsDarkMode } from '
import { UNITAGS_INTRO_BANNER_DARK, UNITAGS_INTRO_BANNER_LIGHT } from 'ui/src/assets' import { UNITAGS_INTRO_BANNER_DARK, UNITAGS_INTRO_BANNER_LIGHT } from 'ui/src/assets'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { setHasCompletedUnitagsIntroModal } from 'wallet/src/features/behaviorHistory/slice'
import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry' import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
...@@ -31,6 +32,8 @@ export function UnitagsIntroModal(): JSX.Element { ...@@ -31,6 +32,8 @@ export function UnitagsIntroModal(): JSX.Element {
if (!entryPoint) { if (!entryPoint) {
throw new Error('Missing entry point in UnitagsIntroModal') throw new Error('Missing entry point in UnitagsIntroModal')
} }
appDispatch(setHasCompletedUnitagsIntroModal(true))
navigate(Screens.UnitagStack, { navigate(Screens.UnitagStack, {
screen: UnitagScreens.ClaimUnitag, screen: UnitagScreens.ClaimUnitag,
params: { params: {
......
...@@ -207,7 +207,7 @@ exports[`GenericImportForm renders a placeholder when there is no value 1`] = ` ...@@ -207,7 +207,7 @@ exports[`GenericImportForm renders a placeholder when there is no value 1`] = `
{ {
"color": "#FC72FF", "color": "#FC72FF",
"fontFamily": "Basel-Medium", "fontFamily": "Basel-Medium",
"fontSize": 13, "fontSize": 15,
"fontWeight": "500", "fontWeight": "500",
"lineHeight": 16, "lineHeight": 16,
} }
......
...@@ -25,7 +25,7 @@ exports[`renders trait card 1`] = ` ...@@ -25,7 +25,7 @@ exports[`renders trait card 1`] = `
{ {
"color": "#7D7D7D", "color": "#7D7D7D",
"fontFamily": "Basel-Medium", "fontFamily": "Basel-Medium",
"fontSize": 13, "fontSize": 15,
"fontWeight": "500", "fontWeight": "500",
"lineHeight": 16, "lineHeight": 16,
} }
......
...@@ -13,7 +13,6 @@ type OnboardingScreenProps = { ...@@ -13,7 +13,6 @@ type OnboardingScreenProps = {
subtitle?: string subtitle?: string
title: string title: string
paddingTop?: SpaceTokens paddingTop?: SpaceTokens
childrenGap?: SpaceTokens
} }
export function SafeKeyboardOnboardingScreen({ export function SafeKeyboardOnboardingScreen({
......
...@@ -9,7 +9,7 @@ import { UnitagProfilePicture } from 'src/components/unitags/UnitagProfilePictur ...@@ -9,7 +9,7 @@ import { UnitagProfilePicture } from 'src/components/unitags/UnitagProfilePictur
import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen' import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen'
import { UnitagName } from 'src/features/unitags/UnitagName' import { UnitagName } from 'src/features/unitags/UnitagName'
import { OnboardingScreens, Screens, UnitagScreens } from 'src/screens/Screens' import { OnboardingScreens, Screens, UnitagScreens } from 'src/screens/Screens'
import { Button, Flex, Icons, Text, useSporeColors } from 'ui/src' import { Button, Flex, Icons, Text, useIsDarkMode, useSporeColors } from 'ui/src'
import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { useENSName } from 'wallet/src/features/ens/api' import { useENSName } from 'wallet/src/features/ens/api'
...@@ -39,6 +39,7 @@ export function ChooseProfilePictureScreen({ ...@@ -39,6 +39,7 @@ export function ChooseProfilePictureScreen({
const colors = useSporeColors() const colors = useSporeColors()
const { data: ensName } = useENSName(address, ChainId.Mainnet) const { data: ensName } = useENSName(address, ChainId.Mainnet)
const claimUnitag = useClaimUnitag() const claimUnitag = useClaimUnitag()
const isDarkMode = useIsDarkMode()
const [imageUri, setImageUri] = useState<string>() const [imageUri, setImageUri] = useState<string>()
const [showModal, setShowModal] = useState(false) const [showModal, setShowModal] = useState(false)
...@@ -116,24 +117,23 @@ export function ChooseProfilePictureScreen({ ...@@ -116,24 +117,23 @@ export function ChooseProfilePictureScreen({
'Upload your own or stick with your unique Unicon. You can always change this later.' 'Upload your own or stick with your unique Unicon. You can always change this later.'
)} )}
title={t('Choose a profile photo')}> title={t('Choose a profile photo')}>
<Flex centered gap="$spacing20" mt="$spacing48"> <Flex centered gap="$spacing20" mt="$spacing24">
<Flex onPress={avatarSelectionHandler}> <Flex mt="$spacing48" onPress={avatarSelectionHandler}>
<Flex px="$spacing4"> <Flex px="$spacing4">
<ProfilePicture address={address} imageUri={imageUri} /> <ProfilePicture address={address} imageUri={imageUri} />
</Flex> </Flex>
<Flex <Flex
backgroundColor="$surface1" backgroundColor="$surface1"
borderRadius="$roundedFull" borderRadius="$roundedFull"
bottom={-spacing.spacing4} bottom={-spacing.spacing2}
p="$spacing4"
position="absolute" position="absolute"
right={-spacing.spacing4}> right={-spacing.spacing2}>
<Flex <Flex
backgroundColor="$neutral2" backgroundColor={isDarkMode ? '$neutral3' : '$neutral2'}
borderColor="$surface1"
borderRadius="$roundedFull" borderRadius="$roundedFull"
borderWidth="$spacing4" p={8}>
p="$spacing8"> <Icons.Pen color={isDarkMode ? '$neutral1' : '$surface1'} size={iconSizes.icon16} />
<Icons.PencilDetailed color="$surface1" size={iconSizes.icon16} />
</Flex> </Flex>
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -23,7 +23,6 @@ import { ...@@ -23,7 +23,6 @@ import {
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { ENS_LOGO } from 'ui/src/assets' import { ENS_LOGO } from 'ui/src/assets'
import InfoCircle from 'ui/src/assets/icons/info-circle.svg'
import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
...@@ -255,6 +254,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element { ...@@ -255,6 +254,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element {
<Flex <Flex
centered centered
gap="$spacing16" gap="$spacing16"
mt="$spacing24"
onLayout={(event): void => { onLayout={(event): void => {
onLayout(event) onLayout(event)
onSetFontSize(inputPlaceholder + UNITAG_SUFFIX_CHARS_ONLY) onSetFontSize(inputPlaceholder + UNITAG_SUFFIX_CHARS_ONLY)
...@@ -331,7 +331,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element { ...@@ -331,7 +331,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element {
Keyboard.dismiss() Keyboard.dismiss()
setShowInfoModal(true) setShowInfoModal(true)
}}> }}>
<InfoCircle color={colors.neutral2.get()} height={20} width={20} /> <Icons.InfoCircleFilled color={colors.neutral3.get()} size="$icon.20" />
</TouchableArea> </TouchableArea>
</AnimatedFlex> </AnimatedFlex>
{canClaimUnitagNameError && unitagToCheck === unitagInputValue && ( {canClaimUnitagNameError && unitagToCheck === unitagInputValue && (
......
...@@ -141,7 +141,7 @@ export const HeartElement = (): JSX.Element => { ...@@ -141,7 +141,7 @@ export const HeartElement = (): JSX.Element => {
<Flex <Flex
borderRadius="$rounded12" borderRadius="$rounded12"
p="$spacing8" p="$spacing8"
style={{ backgroundColor: opacify(20, colors.red200) }} style={{ backgroundColor: colors.red50 }}
transform={[{ rotateZ: '-4deg' }]}> transform={[{ rotateZ: '-4deg' }]}>
<HeartIcon color={colors.red300} height={iconSizes.icon20} width={iconSizes.icon20} /> <HeartIcon color={colors.red300} height={iconSizes.icon20} width={iconSizes.icon20} />
</Flex> </Flex>
......
...@@ -350,7 +350,7 @@ export function EditUnitagProfileScreen({ ...@@ -350,7 +350,7 @@ export function EditUnitagProfileScreen({
mx="$spacing16" mx="$spacing16"
position="absolute" position="absolute"
onPress={avatarSelectionHandler}> onPress={avatarSelectionHandler}>
<Flex backgroundColor="$surface1" borderRadius="$roundedFull" p="$spacing2"> <Flex backgroundColor="$surface1" borderRadius="$roundedFull">
<UnitagProfilePicture <UnitagProfilePicture
address={address} address={address}
size={iconSizes.icon70} size={iconSizes.icon70}
...@@ -370,7 +370,7 @@ export function EditUnitagProfileScreen({ ...@@ -370,7 +370,7 @@ export function EditUnitagProfileScreen({
p={6}> p={6}>
<Icons.Pen <Icons.Pen
color={isDarkMode ? '$neutral1' : '$surface1'} color={isDarkMode ? '$neutral1' : '$surface1'}
size={iconSizes.icon12} size={iconSizes.icon16}
/> />
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -67,6 +67,7 @@ export function UnitagConfirmationScreen({ ...@@ -67,6 +67,7 @@ export function UnitagConfirmationScreen({
<Flex centered grow> <Flex centered grow>
<AnimatePresence exitBeforeEnter> <AnimatePresence exitBeforeEnter>
<AnimateInOrder <AnimateInOrder
key="outerCircle"
enterStyle={{ opacity: 0, scale: 0.5 }} enterStyle={{ opacity: 0, scale: 0.5 }}
exitStyle={{ opacity: 0, scale: 0.5 }} exitStyle={{ opacity: 0, scale: 0.5 }}
index={1} index={1}
...@@ -80,6 +81,7 @@ export function UnitagConfirmationScreen({ ...@@ -80,6 +81,7 @@ export function UnitagConfirmationScreen({
/> />
</AnimateInOrder> </AnimateInOrder>
<AnimateInOrder <AnimateInOrder
key="innerCircle"
enterStyle={{ opacity: 0, scale: 0.5 }} enterStyle={{ opacity: 0, scale: 0.5 }}
exitStyle={{ opacity: 0, scale: 0.5 }} exitStyle={{ opacity: 0, scale: 0.5 }}
index={2} index={2}
...@@ -102,7 +104,7 @@ export function UnitagConfirmationScreen({ ...@@ -102,7 +104,7 @@ export function UnitagConfirmationScreen({
{element} {element}
</AnimateInOrder> </AnimateInOrder>
))} ))}
<AnimateInOrder hapticOnEnter index={12}> <AnimateInOrder key="unitag" hapticOnEnter index={12}>
<UnitagWithProfilePicture <UnitagWithProfilePicture
address={address} address={address}
profilePictureUri={profilePictureUri} profilePictureUri={profilePictureUri}
......
import { Flex, Icons, Text } from 'ui/src' import { Flex, Icons, Text } from 'ui/src'
import { fonts, iconSizes } from 'ui/src/theme' import { fonts, spacing } from 'ui/src/theme'
export function UnitagName({ export function UnitagName({
name, name,
...@@ -35,8 +35,8 @@ export function UnitagName({ ...@@ -35,8 +35,8 @@ export function UnitagName({
enterStyle={animateIcon ? { opacity: 0, scale: 0.8, x: 20 } : undefined} enterStyle={animateIcon ? { opacity: 0, scale: 0.8, x: 20 } : undefined}
exitStyle={animateIcon ? { opacity: 0, scale: 0.8, x: -20 } : undefined} exitStyle={animateIcon ? { opacity: 0, scale: 0.8, x: -20 } : undefined}
position="absolute" position="absolute"
right={-iconSizes.icon8} right={-spacing.spacing4}
top={-iconSizes.icon8}> top={-spacing.spacing4}>
<Icons.Unitag size="$icon.24" /> <Icons.Unitag size="$icon.24" />
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -59,7 +59,7 @@ function useLineItem(details: OffchainOrderLineItemProps): LineItemData | undefi ...@@ -59,7 +59,7 @@ function useLineItem(details: OffchainOrderLineItemProps): LineItemData | undefi
case OffchainOrderLineItemType.EXPIRY: case OffchainOrderLineItemType.EXPIRY:
return { return {
Label: () => <Trans>Expiry</Trans>, Label: () => <Trans>Expiry</Trans>,
Value: () => <span>{formatTimestamp(details.order.expiry)}</span>, Value: () => <span>{details.order.expiry && formatTimestamp(details.order.expiry * 1000)}</span>,
} }
case OffchainOrderLineItemType.NETWORK_COST: case OffchainOrderLineItemType.NETWORK_COST:
return { return {
......
...@@ -1046,9 +1046,7 @@ exports[`OrderContent should render without error, open order 1`] = ` ...@@ -1046,9 +1046,7 @@ exports[`OrderContent should render without error, open order 1`] = `
<div <div
class="c6 c20 css-142zc9n" class="c6 c20 css-142zc9n"
> >
<span> <span />
Mock Date
</span>
</div> </div>
</div> </div>
<div <div
......
...@@ -25,7 +25,7 @@ import { PositionInfo } from './cache' ...@@ -25,7 +25,7 @@ import { PositionInfo } from './cache'
type ContractMap<T extends BaseContract> = { [key: number]: T } type ContractMap<T extends BaseContract> = { [key: number]: T }
// Constructs a chain-to-contract map, using the wallet's provider when available // Constructs a chain-to-contract map, using the wallet's provider when available
function useContractMultichain<T extends BaseContract>( export function useContractMultichain<T extends BaseContract>(
addressMap: AddressMap, addressMap: AddressMap,
ABI: any, ABI: any,
chainIds?: ChainId[] chainIds?: ChainId[]
......
import { ChartHoverData, ChartModel, ChartModelParams } from 'components/Charts/ChartModel' import { ChartHoverData, ChartModel, ChartModelParams } from 'components/Charts/ChartModel'
import { ISeriesApi, UTCTimestamp } from 'lightweight-charts' import { ISeriesApi, UTCTimestamp } from 'lightweight-charts'
import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { ChainId, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { FeeAmount, Pool, TICK_SPACINGS, TickMath, tickToPrice } from '@uniswap/v3-sdk' import { FeeAmount, Pool, TICK_SPACINGS, TickMath, tickToPrice } from '@uniswap/v3-sdk'
import { BigNumber } from 'ethers/lib/ethers' import { BigNumber } from 'ethers/lib/ethers'
import { TickProcessed, usePoolActiveLiquidity } from 'hooks/usePoolTickData' import { TickProcessed, usePoolActiveLiquidity } from 'hooks/usePoolTickData'
...@@ -221,14 +221,16 @@ export function useLiquidityBarData({ ...@@ -221,14 +221,16 @@ export function useLiquidityBarData({
tokenB, tokenB,
feeTier, feeTier,
isReversed, isReversed,
chainId,
}: { }: {
tokenA: Token tokenA: Token
tokenB: Token tokenB: Token
feeTier: FeeAmount feeTier: FeeAmount
isReversed: boolean isReversed: boolean
chainId: ChainId
}) { }) {
const { formatNumber, formatPrice } = useFormatter() const { formatNumber, formatPrice } = useFormatter()
const activePoolData = usePoolActiveLiquidity(tokenA, tokenB, feeTier) const activePoolData = usePoolActiveLiquidity(tokenA, tokenB, feeTier, chainId)
const [tickData, setTickData] = useState<{ const [tickData, setTickData] = useState<{
barData: LiquidityBarData[] barData: LiquidityBarData[]
......
import { Trans, t } from '@lingui/macro' import { Trans, t } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { ChainId, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import { ChartHeader } from 'components/Charts/ChartHeader' import { ChartHeader } from 'components/Charts/ChartHeader'
import { Chart } from 'components/Charts/ChartModel' import { Chart } from 'components/Charts/ChartModel'
...@@ -19,7 +19,7 @@ import { LoadingChart } from 'components/Tokens/TokenDetails/Skeleton' ...@@ -19,7 +19,7 @@ import { LoadingChart } from 'components/Tokens/TokenDetails/Skeleton'
import { DISPLAYS, TimePeriodDisplay, getTimePeriodFromDisplay } from 'components/Tokens/TokenTable/TimeSelector' import { DISPLAYS, TimePeriodDisplay, getTimePeriodFromDisplay } from 'components/Tokens/TokenTable/TimeSelector'
import { Chain, ProtocolVersion } from 'graphql/data/__generated__/types-and-hooks' import { Chain, ProtocolVersion } from 'graphql/data/__generated__/types-and-hooks'
import { PoolData } from 'graphql/data/pools/usePoolData' import { PoolData } from 'graphql/data/pools/usePoolData'
import { TimePeriod, gqlToCurrency, toHistoryDuration } from 'graphql/data/util' import { TimePeriod, gqlToCurrency, supportedChainIdFromGQLChain, toHistoryDuration } from 'graphql/data/util'
import useStablecoinPrice from 'hooks/useStablecoinPrice' import useStablecoinPrice from 'hooks/useStablecoinPrice'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import { useMemo, useState } from 'react' import { useMemo, useState } from 'react'
...@@ -152,7 +152,7 @@ export default function ChartSection(props: ChartSectionProps) { ...@@ -152,7 +152,7 @@ export default function ChartSection(props: ChartSectionProps) {
const loading = props.loading || (activeQuery.chartType !== ChartType.LIQUIDITY ? activeQuery?.loading : false) const loading = props.loading || (activeQuery.chartType !== ChartType.LIQUIDITY ? activeQuery?.loading : false)
const ChartBody = (() => { const ChartBody = (() => {
if (!currencyA || !currencyB || !props.poolData) { if (!currencyA || !currencyB || !props.poolData || !props.chain) {
return <ChartSkeleton type={activeQuery.chartType} height={PDP_CHART_HEIGHT_PX} /> return <ChartSkeleton type={activeQuery.chartType} height={PDP_CHART_HEIGHT_PX} />
} }
...@@ -163,6 +163,7 @@ export default function ChartSection(props: ChartSectionProps) { ...@@ -163,6 +163,7 @@ export default function ChartSection(props: ChartSectionProps) {
timePeriod, timePeriod,
tokenA: currencyA.wrapped, tokenA: currencyA.wrapped,
tokenB: currencyB.wrapped, tokenB: currencyB.wrapped,
chainId: supportedChainIdFromGQLChain(props.chain) ?? ChainId.MAINNET,
} }
// TODO(WEB-3740): Integrate BE tick query, remove special casing for liquidity chart // TODO(WEB-3740): Integrate BE tick query, remove special casing for liquidity chart
...@@ -328,11 +329,13 @@ function LiquidityChart({ ...@@ -328,11 +329,13 @@ function LiquidityChart({
tokenB, tokenB,
feeTier, feeTier,
isReversed, isReversed,
chainId,
}: { }: {
tokenA: Token tokenA: Token
tokenB: Token tokenB: Token
feeTier: FeeAmount feeTier: FeeAmount
isReversed: boolean isReversed: boolean
chainId: ChainId
}) { }) {
const tokenADescriptor = tokenA.symbol ?? tokenA.name ?? t`Token A` const tokenADescriptor = tokenA.symbol ?? tokenA.name ?? t`Token A`
const tokenBDescriptor = tokenB.symbol ?? tokenB.name ?? t`Token B` const tokenBDescriptor = tokenB.symbol ?? tokenB.name ?? t`Token B`
...@@ -342,6 +345,7 @@ function LiquidityChart({ ...@@ -342,6 +345,7 @@ function LiquidityChart({
tokenB, tokenB,
feeTier, feeTier,
isReversed, isReversed,
chainId,
}) })
const theme = useTheme() const theme = useTheme()
......
...@@ -124,6 +124,10 @@ describe('SwapModalFooter.tsx', () => { ...@@ -124,6 +124,10 @@ describe('SwapModalFooter.tsx', () => {
expect(screen.getByText('Expiry')).toBeInTheDocument() expect(screen.getByText('Expiry')).toBeInTheDocument()
expect(screen.getByText('Fee')).toBeInTheDocument() expect(screen.getByText('Fee')).toBeInTheDocument()
expect(screen.getByText('Network cost')).toBeInTheDocument() expect(screen.getByText('Network cost')).toBeInTheDocument()
expect(screen.getByText('Canceling a limit will require a small network cost')).toBeInTheDocument() expect(
screen.getByText(
'Please be aware that the execution for this limit order may vary based on real-time market fluctuations and Ethereum network congestion. Canceling a limit has a network cost.'
)
).toBeInTheDocument()
}) })
}) })
...@@ -327,6 +327,12 @@ function ExpandableLineItems(props: { trade: InterfaceTrade; allowedSlippage: Pe ...@@ -327,6 +327,12 @@ function ExpandableLineItems(props: { trade: InterfaceTrade; allowedSlippage: Pe
) )
} }
const StyledInfoIcon = styled(Info)`
margin-top: 2px;
align-self: flex-start;
flex-shrink: 0;
`
function LimitLineItems({ trade }: { trade: LimitOrderTrade }) { function LimitLineItems({ trade }: { trade: LimitOrderTrade }) {
return ( return (
<> <>
...@@ -334,10 +340,16 @@ function LimitLineItems({ trade }: { trade: LimitOrderTrade }) { ...@@ -334,10 +340,16 @@ function LimitLineItems({ trade }: { trade: LimitOrderTrade }) {
<SwapLineItem trade={trade} type={SwapLineItemType.EXPIRY} /> <SwapLineItem trade={trade} type={SwapLineItemType.EXPIRY} />
<SwapLineItem trade={trade} type={SwapLineItemType.SWAP_FEE} /> <SwapLineItem trade={trade} type={SwapLineItemType.SWAP_FEE} />
<SwapLineItem trade={trade} type={SwapLineItemType.NETWORK_COST} /> <SwapLineItem trade={trade} type={SwapLineItemType.NETWORK_COST} />
<Row gap="xs" justify="center" marginTop="12px"> <Row gap="sm" justify="space-between" marginTop="12px">
<Info width={16} height={16} /> <StyledInfoIcon width={16} height={16} />
<ThemedText.LabelMicro> <ThemedText.LabelMicro>
<Trans>Canceling a limit will require a small network cost</Trans> <Trans>
Please be aware that the execution for this limit order may vary based on real-time market fluctuations and
Ethereum network congestion. Canceling a limit has a network cost.{' '}
<ExternalLink href="https://support.uniswap.org/hc/en-us/articles/24300813697933">
<Trans>Learn more</Trans>
</ExternalLink>
</Trans>
</ThemedText.LabelMicro> </ThemedText.LabelMicro>
</Row> </Row>
</> </>
......
import { ApolloClient, ApolloLink, concat, HttpLink, InMemoryCache } from '@apollo/client' import { ApolloClient, ApolloLink, concat, HttpLink, InMemoryCache, NormalizedCacheObject } from '@apollo/client'
import { ChainId } from '@uniswap/sdk-core' import { ChainId } from '@uniswap/sdk-core'
import store from '../../state/index' import store from '../../state/index'
...@@ -33,3 +33,34 @@ export const apolloClient = new ApolloClient({ ...@@ -33,3 +33,34 @@ export const apolloClient = new ApolloClient({
cache: new InMemoryCache(), cache: new InMemoryCache(),
link: concat(authMiddleware, httpLink), link: concat(authMiddleware, httpLink),
}) })
export const chainToApolloClient: Record<number, ApolloClient<NormalizedCacheObject>> = {
[ChainId.MAINNET]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.MAINNET],
}),
[ChainId.ARBITRUM_ONE]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.ARBITRUM_ONE],
}),
[ChainId.OPTIMISM]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.OPTIMISM],
}),
[ChainId.POLYGON]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.POLYGON],
}),
[ChainId.CELO]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.CELO],
}),
[ChainId.BNB]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.BNB],
}),
[ChainId.AVALANCHE]: new ApolloClient({
cache: new InMemoryCache(),
uri: CHAIN_SUBGRAPH_URL[ChainId.AVALANCHE],
}),
}
import { Currency, Price, Token, V3_CORE_FACTORY_ADDRESSES } from '@uniswap/sdk-core' import { ChainId, Currency, Price, Token, V3_CORE_FACTORY_ADDRESSES } from '@uniswap/sdk-core'
import { FeeAmount, Pool, TICK_SPACINGS, tickToPrice } from '@uniswap/v3-sdk' import { FeeAmount, Pool, TICK_SPACINGS, tickToPrice } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { TickData, Ticks } from 'graphql/thegraph/AllV3TicksQuery' import { TickData, Ticks } from 'graphql/thegraph/AllV3TicksQuery'
import { useAllV3TicksQuery } from 'graphql/thegraph/__generated__/types-and-hooks' import { useAllV3TicksQuery } from 'graphql/thegraph/__generated__/types-and-hooks'
import { apolloClient } from 'graphql/thegraph/apollo'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import ms from 'ms' import ms from 'ms'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import computeSurroundingTicks from 'utils/computeSurroundingTicks' import computeSurroundingTicks from 'utils/computeSurroundingTicks'
import { PoolState, usePool } from './usePools' import { chainToApolloClient } from 'graphql/thegraph/apollo'
import { PoolState, usePoolMultichain } from './usePools'
const PRICE_FIXED_DIGITS = 8 const PRICE_FIXED_DIGITS = 8
...@@ -29,9 +29,10 @@ function useTicksFromSubgraph( ...@@ -29,9 +29,10 @@ function useTicksFromSubgraph(
currencyA: Currency | undefined, currencyA: Currency | undefined,
currencyB: Currency | undefined, currencyB: Currency | undefined,
feeAmount: FeeAmount | undefined, feeAmount: FeeAmount | undefined,
skip = 0 skip = 0,
chainId: ChainId
) { ) {
const { chainId } = useWeb3React() const apolloClient = chainToApolloClient[chainId]
const poolAddress = const poolAddress =
currencyA && currencyB && feeAmount currencyA && currencyB && feeAmount
? Pool.getAddress( ? Pool.getAddress(
...@@ -56,7 +57,8 @@ const MAX_THE_GRAPH_TICK_FETCH_VALUE = 1000 ...@@ -56,7 +57,8 @@ const MAX_THE_GRAPH_TICK_FETCH_VALUE = 1000
function useAllV3Ticks( function useAllV3Ticks(
currencyA: Currency | undefined, currencyA: Currency | undefined,
currencyB: Currency | undefined, currencyB: Currency | undefined,
feeAmount: FeeAmount | undefined feeAmount: FeeAmount | undefined,
chainId: ChainId
): { ): {
isLoading: boolean isLoading: boolean
error: unknown error: unknown
...@@ -64,7 +66,7 @@ function useAllV3Ticks( ...@@ -64,7 +66,7 @@ function useAllV3Ticks(
} { } {
const [skipNumber, setSkipNumber] = useState(0) const [skipNumber, setSkipNumber] = useState(0)
const [subgraphTickData, setSubgraphTickData] = useState<Ticks>([]) const [subgraphTickData, setSubgraphTickData] = useState<Ticks>([])
const { data, error, loading: isLoading } = useTicksFromSubgraph(currencyA, currencyB, feeAmount, skipNumber) const { data, error, loading: isLoading } = useTicksFromSubgraph(currencyA, currencyB, feeAmount, skipNumber, chainId)
useEffect(() => { useEffect(() => {
if (data?.ticks.length) { if (data?.ticks.length) {
...@@ -85,7 +87,8 @@ function useAllV3Ticks( ...@@ -85,7 +87,8 @@ function useAllV3Ticks(
export function usePoolActiveLiquidity( export function usePoolActiveLiquidity(
currencyA: Currency | undefined, currencyA: Currency | undefined,
currencyB: Currency | undefined, currencyB: Currency | undefined,
feeAmount: FeeAmount | undefined feeAmount: FeeAmount | undefined,
chainId?: ChainId
): { ): {
isLoading: boolean isLoading: boolean
error: any error: any
...@@ -95,7 +98,8 @@ export function usePoolActiveLiquidity( ...@@ -95,7 +98,8 @@ export function usePoolActiveLiquidity(
sqrtPriceX96?: JSBI sqrtPriceX96?: JSBI
data?: TickProcessed[] data?: TickProcessed[]
} { } {
const pool = usePool(currencyA, currencyB, feeAmount) const defaultChainId = useWeb3React().chainId ?? ChainId.MAINNET
const pool = usePoolMultichain(currencyA?.wrapped, currencyB?.wrapped, feeAmount, chainId ?? defaultChainId)
const liquidity = pool[1]?.liquidity const liquidity = pool[1]?.liquidity
const sqrtPriceX96 = pool[1]?.sqrtRatioX96 const sqrtPriceX96 = pool[1]?.sqrtRatioX96
...@@ -103,7 +107,7 @@ export function usePoolActiveLiquidity( ...@@ -103,7 +107,7 @@ export function usePoolActiveLiquidity(
// Find nearest valid tick for pool in case tick is not initialized. // Find nearest valid tick for pool in case tick is not initialized.
const activeTick = useMemo(() => getActiveTick(currentTick, feeAmount), [currentTick, feeAmount]) const activeTick = useMemo(() => getActiveTick(currentTick, feeAmount), [currentTick, feeAmount])
const { isLoading, error, ticks } = useAllV3Ticks(currencyA, currencyB, feeAmount) const { isLoading, error, ticks } = useAllV3Ticks(currencyA, currencyB, feeAmount, chainId ?? defaultChainId)
return useMemo(() => { return useMemo(() => {
if ( if (
......
import { Interface } from '@ethersproject/abi' import { Interface } from '@ethersproject/abi'
import { BigintIsh, Currency, Token, V3_CORE_FACTORY_ADDRESSES } from '@uniswap/sdk-core' import { BigintIsh, ChainId, Currency, Token, V3_CORE_FACTORY_ADDRESSES } from '@uniswap/sdk-core'
import IUniswapV3PoolStateJSON from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json' import IUniswapV3PoolStateJSON from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import { FeeAmount, Pool, computePoolAddress } from '@uniswap/v3-sdk' import { FeeAmount, Pool, computePoolAddress } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { useContractMultichain } from 'components/AccountDrawer/MiniPortfolio/Pools/hooks'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { useMultipleContractSingleData } from 'lib/hooks/multicall' import { useMultipleContractSingleData } from 'lib/hooks/multicall'
import { useMemo } from 'react' import { useEffect, useMemo, useState } from 'react'
import { IUniswapV3PoolStateInterface } from 'wallet/src/abis/types/v3/IUniswapV3PoolState' import { IUniswapV3PoolStateInterface } from 'wallet/src/abis/types/v3/IUniswapV3PoolState'
import { UniswapV3Pool } from 'wallet/src/abis/types/v3/UniswapV3Pool'
const POOL_STATE_INTERFACE = new Interface(IUniswapV3PoolStateJSON.abi) as IUniswapV3PoolStateInterface const POOL_STATE_INTERFACE = new Interface(IUniswapV3PoolStateJSON.abi) as IUniswapV3PoolStateInterface
...@@ -150,3 +152,41 @@ export function usePool( ...@@ -150,3 +152,41 @@ export function usePool(
return usePools(poolKeys)[0] return usePools(poolKeys)[0]
} }
export function usePoolMultichain(
tokenA: Token | undefined,
tokenB: Token | undefined,
fee: number | undefined,
chainId: ChainId
): [PoolState, Pool | null] {
const [poolData, setPoolData] = useState<[PoolState, Pool | null]>([PoolState.LOADING, null])
const poolAddress =
tokenA && tokenB && fee
? PoolCache.getPoolAddress(V3_CORE_FACTORY_ADDRESSES[chainId], tokenA, tokenB, fee)
: undefined
const contractMap = useMemo(() => (poolAddress ? { [chainId]: poolAddress } : {}), [chainId, poolAddress])
const contract = useContractMultichain<UniswapV3Pool>(contractMap, IUniswapV3PoolStateJSON.abi)[chainId]
useEffect(() => {
async function getPool() {
try {
if (!tokenA || !tokenB || !fee || !poolAddress || !contract) {
setPoolData([PoolState.INVALID, null])
return
}
const slot0 = await contract.slot0()
const liquidity = await contract.liquidity()
setPoolData([PoolState.NOT_EXISTS, null])
const pool = new Pool(tokenA, tokenB, fee, slot0.sqrtPriceX96.toString(), liquidity.toString(), slot0.tick)
setPoolData([PoolState.EXISTS, pool])
} catch (e) {
setPoolData([PoolState.INVALID, null])
}
}
getPool()
}, [contract, fee, poolAddress, tokenA, tokenB])
return poolData
}
import { danger, fail, markdown, message, warn } from 'danger' import { danger, fail, markdown, message, warn } from 'danger'
// Other ideas:
// - verify TODO have work items linked
function getIndicesOf(searchStr: string, str: string): number[] { function getIndicesOf(searchStr: string, str: string): number[] {
var searchStrLen = searchStr.length; var searchStrLen = searchStr.length;
if (searchStrLen == 0) { if (searchStrLen == 0) {
...@@ -16,21 +13,35 @@ function getIndicesOf(searchStr: string, str: string): number[] { ...@@ -16,21 +13,35 @@ function getIndicesOf(searchStr: string, str: string): number[] {
return indices; return indices;
} }
async function processAddChanges() { async function getLinesAddedByFile(files: string[]) {
const updatedTsFiles = danger.git.modified_files return await Promise.all(files.flatMap(async (file) => {
.concat(danger.git.created_files)
.filter((file) => (file.endsWith('.ts') || file.endsWith('.tsx')) && !file.includes('dangerfile.ts'))
const linesAddedByFile = (await Promise.all(updatedTsFiles.flatMap(async (file) => {
const structuredDiff = await danger.git.structuredDiffForFile(file); const structuredDiff = await danger.git.structuredDiffForFile(file);
return (structuredDiff?.chunks || []).flatMap((chunk) => { return (structuredDiff?.chunks || []).flatMap((chunk) => {
return chunk.changes.filter((change) => change.type === 'add') return chunk.changes.filter((change) => change.type === 'add')
}) })
}))) }))
}
async function processAddChanges() {
const updatedTsFiles = danger.git.modified_files
.concat(danger.git.created_files)
.filter((file) => (file.endsWith('.ts') || file.endsWith('.tsx')) && !file.includes('dangerfile.ts'))
const updatedNonUITsFiles = updatedTsFiles.filter((file) => !file.includes('packages/ui'))
const linesAddedByFile = await getLinesAddedByFile(updatedTsFiles)
const allLinesAdded = linesAddedByFile.flatMap((x) => x) const allLinesAdded = linesAddedByFile.flatMap((x) => x)
// Check for non-UI package lines for tamagui imports
const allNonUILinesAddedByFile = await getLinesAddedByFile(updatedNonUITsFiles)
const allNonUILinesAdded = allNonUILinesAddedByFile.flatMap((x) => x)
allNonUILinesAdded.forEach((change) => {
if (change.content.includes(`from 'tamagui`)) {
fail(`Please import any tamagui exports via the ui package. Found an import at ${change.content}`)
}
})
// Checks for any logging and reminds the developer not to log sensitive data // Checks for any logging and reminds the developer not to log sensitive data
if (allLinesAdded.some((change) => change.content.includes('logMessage') || change.content.includes('logger.'))) { if (allLinesAdded.some((change) => change.content.includes('logMessage') || change.content.includes('logger.'))) {
warn('You are logging data. Please confirm that nothing sensitive is being logged!') warn('You are logging data. Please confirm that nothing sensitive is being logged!')
......
...@@ -18,9 +18,11 @@ export { ...@@ -18,9 +18,11 @@ export {
YGroup, YGroup,
getToken, getToken,
getTokenValue, getTokenValue,
isWeb,
styled, styled,
useMedia, useMedia,
usePropsAndStyle, usePropsAndStyle,
useWindowDimensions,
} from 'tamagui' } from 'tamagui'
export type { export type {
Adapt, Adapt,
......
...@@ -125,7 +125,7 @@ export const fonts = { ...@@ -125,7 +125,7 @@ export const fonts = {
}, },
buttonLabel4: { buttonLabel4: {
family: platformFontFamily('medium'), family: platformFontFamily('medium'),
fontSize: adjustedSize(12), fontSize: adjustedSize(14),
lineHeight: 16, lineHeight: 16,
fontWeight: '500', fontWeight: '500',
maxFontSizeMultiplier: 1.2, maxFontSizeMultiplier: 1.2,
......
...@@ -74,7 +74,6 @@ ...@@ -74,7 +74,6 @@
"redux-saga": "1.2.2", "redux-saga": "1.2.2",
"redux-saga-test-plan": "4.0.4", "redux-saga-test-plan": "4.0.4",
"statsig-react-native": "4.11.0", "statsig-react-native": "4.11.0",
"tamagui": "1.89.26",
"typed-redux-saga": "1.5.0", "typed-redux-saga": "1.5.0",
"ua-parser-js": "1.0.37", "ua-parser-js": "1.0.37",
"ui": "workspace:^", "ui": "workspace:^",
......
import { BottomSheetSectionList } from '@gorhom/bottom-sheet' import { BottomSheetSectionList } from '@gorhom/bottom-sheet'
import { ListRenderItemInfo, SectionList, SectionListData } from 'react-native' import { ListRenderItemInfo, SectionList, SectionListData } from 'react-native'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import { AnimatedFlex, Text, TouchableArea, isWeb, useDeviceInsets } from 'ui/src'
import { AnimatedFlex, Text, TouchableArea, useDeviceInsets } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
import { SearchableRecipient } from 'wallet/src/features/address/types' import { SearchableRecipient } from 'wallet/src/features/address/types'
......
import { ImpactFeedbackStyle } from 'expo-haptics' import { ImpactFeedbackStyle } from 'expo-haptics'
import { memo } from 'react' import { memo } from 'react'
import { isWeb } from 'tamagui' import { isWeb, TouchableArea, useSporeColors } from 'ui/src'
import { TouchableArea, useSporeColors } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { TokenLogo } from 'wallet/src/components/CurrencyLogo/TokenLogo' import { TokenLogo } from 'wallet/src/components/CurrencyLogo/TokenLogo'
import { Pill } from 'wallet/src/components/text/Pill' import { Pill } from 'wallet/src/components/text/Pill'
......
import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import AutoSizer from 'react-virtualized-auto-sizer' import AutoSizer from 'react-virtualized-auto-sizer'
import { VariableSizeList as List } from 'react-window' import { VariableSizeList as List } from 'react-window'
import { useWindowDimensions } from 'tamagui' import { Flex, useWindowDimensions } from 'ui/src'
import { Flex } from 'ui/src'
import { zIndices } from 'ui/src/theme' import { zIndices } from 'ui/src/theme'
import { import {
ItemRowInfo, ItemRowInfo,
......
...@@ -3,8 +3,7 @@ import { hasStringAsync } from 'expo-clipboard' ...@@ -3,8 +3,7 @@ import { hasStringAsync } from 'expo-clipboard'
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard } from 'react-native' import { Keyboard } from 'react-native'
import { isWeb } from 'tamagui' import { Flex, isWeb, useSporeColors } from 'ui/src'
import { Flex, useSporeColors } from 'ui/src'
import { zIndices } from 'ui/src/theme' import { zIndices } from 'ui/src/theme'
import { Trace } from 'utilities/src/telemetry/trace/Trace' import { Trace } from 'utilities/src/telemetry/trace/Trace'
import { useDebounce } from 'utilities/src/time/timing' import { useDebounce } from 'utilities/src/time/timing'
......
import { memo, useCallback, useEffect, useRef } from 'react' import { memo, useCallback, useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import { AnimatedFlex, Flex, isWeb, Loader, Skeleton, Text } from 'ui/src'
import { AnimatedFlex, Flex, Loader, Skeleton, Text } from 'ui/src'
import { fonts } from 'ui/src/theme' import { fonts } from 'ui/src/theme'
import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard' import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard'
import { useBottomSheetFocusHook } from 'wallet/src/components/modals/hooks' import { useBottomSheetFocusHook } from 'wallet/src/components/modals/hooks'
......
import { skipToken } from '@reduxjs/toolkit/dist/query' import { skipToken } from '@reduxjs/toolkit/dist/query'
import { memo, useMemo } from 'react' import { memo, useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { Flex, isWeb } from 'ui/src'
import { Flex } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard' import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard'
import { SpinningLoader } from 'wallet/src/components/loading/SpinningLoader' import { SpinningLoader } from 'wallet/src/components/loading/SpinningLoader'
......
import { memo, useCallback, useMemo } from 'react' import { memo, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { isWeb } from 'ui/src'
import { import {
useCommonTokensOptions, useCommonTokensOptions,
useFavoriteTokensOptions, useFavoriteTokensOptions,
......
import { StyleSheet } from 'react-native' import { StyleSheet } from 'react-native'
import Svg, { Defs, RadialGradient as RadialGradientSVG, Rect, Stop } from 'react-native-svg' import Svg, { Defs, RadialGradient as RadialGradientSVG, Rect, Stop } from 'react-native-svg'
import { isWeb } from 'tamagui' import { ColorTokens, Flex, Icons, Unicon, UniconV2, isWeb, useUniconColors } from 'ui/src'
import { ColorTokens, Flex, Icons, Unicon, UniconV2, useUniconColors } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants' import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants'
import { useFeatureFlag } from 'wallet/src/features/experiments/hooks' import { useFeatureFlag } from 'wallet/src/features/experiments/hooks'
......
...@@ -165,6 +165,8 @@ export function AddressDisplay({ ...@@ -165,6 +165,8 @@ export function AddressDisplay({
<Flex centered row gap="$spacing12"> <Flex centered row gap="$spacing12">
<DisplayNameText <DisplayNameText
displayName={displayName} displayName={displayName}
gap="$spacing4"
includeUnitagSuffix={includeUnitagSuffix}
textProps={{ textProps={{
adjustsFontSizeToFit: true, adjustsFontSizeToFit: true,
allowFontScaling, allowFontScaling,
......
...@@ -68,7 +68,7 @@ export function AnimatedUnitagDisplayName({ ...@@ -68,7 +68,7 @@ export function AnimatedUnitagDisplayName({
</Text> </Text>
</Flex> </Flex>
{isUnitag ? ( {isUnitag ? (
<Flex animation="semiBouncy" pl="$spacing2"> <Flex animation="semiBouncy" pl="$spacing4">
<Icons.Unitag size={unitagIconSize} /> <Icons.Unitag size={unitagIconSize} />
</Flex> </Flex>
) : null} ) : null}
......
import { Flex, FlexProps, Icons, Text, TextProps } from 'ui/src' import { Flex, FlexProps, Icons, Text, TextProps } from 'ui/src'
import { IconSizeTokens } from 'ui/src/theme' import { IconSizeTokens } from 'ui/src/theme'
import { UNITAG_SUFFIX } from 'wallet/src/features/unitags/constants'
import { DisplayName, DisplayNameType } from 'wallet/src/features/wallet/types' import { DisplayName, DisplayNameType } from 'wallet/src/features/wallet/types'
type DisplayNameProps = { type DisplayNameProps = {
displayName?: DisplayName displayName?: DisplayName
unitagIconSize?: IconSizeTokens | number unitagIconSize?: IconSizeTokens | number
textProps?: TextProps textProps?: TextProps
includeUnitagSuffix?: boolean
} & FlexProps } & FlexProps
export function DisplayNameText({ export function DisplayNameText({
displayName, displayName,
unitagIconSize = '$icon.24', unitagIconSize = '$icon.24',
textProps, textProps,
includeUnitagSuffix,
...rest ...rest
}: DisplayNameProps): JSX.Element { }: DisplayNameProps): JSX.Element {
const isUnitag = displayName?.type === DisplayNameType.Unitag const isUnitag = displayName?.type === DisplayNameType.Unitag
const name = isUnitag ? displayName?.name.replaceAll(UNITAG_SUFFIX, '') : displayName?.name
return ( return (
<Flex centered row {...rest}> <Flex centered row {...rest}>
<Text {...textProps} color={textProps?.color ?? '$neutral1'} flexShrink={1} numberOfLines={1}> <Text {...textProps} color={textProps?.color ?? '$neutral1'} flexShrink={1} numberOfLines={1}>
{displayName?.name} {name}
{isUnitag && includeUnitagSuffix && (
<Text {...textProps} color="$neutral3" flexShrink={1} numberOfLines={1}>
{UNITAG_SUFFIX}
</Text>
)}
</Text> </Text>
{isUnitag ? ( {isUnitag ? (
<Flex> <Flex>
......
...@@ -274,6 +274,7 @@ exports[`AccountDetails renders without error 1`] = ` ...@@ -274,6 +274,7 @@ exports[`AccountDetails renders without error 1`] = `
{ {
"alignItems": "center", "alignItems": "center",
"flexDirection": "row", "flexDirection": "row",
"gap": 4,
"justifyContent": "center", "justifyContent": "center",
} }
} }
...@@ -607,6 +608,7 @@ exports[`AccountDetails renders without error with chevron 1`] = ` ...@@ -607,6 +608,7 @@ exports[`AccountDetails renders without error with chevron 1`] = `
{ {
"alignItems": "center", "alignItems": "center",
"flexDirection": "row", "flexDirection": "row",
"gap": 4,
"justifyContent": "center", "justifyContent": "center",
} }
} }
......
import { selectionAsync } from 'expo-haptics' import { selectionAsync } from 'expo-haptics'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { LayoutAnimation, StyleSheet, VirtualizedList } from 'react-native' import { LayoutAnimation, StyleSheet, VirtualizedList } from 'react-native'
import { isWeb } from 'tamagui' import { Flex, Icons, isWeb } from 'ui/src'
import { Flex, Icons } from 'ui/src'
import EllipsisIcon from 'ui/src/assets/icons/ellipsis.svg' import EllipsisIcon from 'ui/src/assets/icons/ellipsis.svg'
import { colors, iconSizes } from 'ui/src/theme' import { colors, iconSizes } from 'ui/src/theme'
import { import {
......
...@@ -123,7 +123,7 @@ exports[`NetworkPill renders an InlineNetworkPill 1`] = ` ...@@ -123,7 +123,7 @@ exports[`NetworkPill renders an InlineNetworkPill 1`] = `
{ {
"color": "#209853", "color": "#209853",
"fontFamily": "Basel-Medium", "fontFamily": "Basel-Medium",
"fontSize": 13, "fontSize": 15,
"fontWeight": "500", "fontWeight": "500",
"lineHeight": 16, "lineHeight": 16,
"paddingTop": 1, "paddingTop": 1,
......
...@@ -8,3 +8,6 @@ export const selectHasSubmittedHoldToSwap = (state: SharedState): boolean => ...@@ -8,3 +8,6 @@ export const selectHasSubmittedHoldToSwap = (state: SharedState): boolean =>
export const selectHasSkippedUnitagPrompt = (state: SharedState): boolean => export const selectHasSkippedUnitagPrompt = (state: SharedState): boolean =>
state.behaviorHistory.hasSkippedUnitagPrompt state.behaviorHistory.hasSkippedUnitagPrompt
export const selectHasCompletedUnitagsIntroModal = (state: SharedState): boolean =>
state.behaviorHistory.hasCompletedUnitagsIntroModal
...@@ -8,12 +8,14 @@ export interface BehaviorHistoryState { ...@@ -8,12 +8,14 @@ export interface BehaviorHistoryState {
hasViewedReviewScreen: boolean // used for hold to swap tip on swap UI hasViewedReviewScreen: boolean // used for hold to swap tip on swap UI
hasSubmittedHoldToSwap: boolean hasSubmittedHoldToSwap: boolean
hasSkippedUnitagPrompt: boolean hasSkippedUnitagPrompt: boolean
hasCompletedUnitagsIntroModal: boolean
} }
export const initialBehaviorHistoryState: BehaviorHistoryState = { export const initialBehaviorHistoryState: BehaviorHistoryState = {
hasViewedReviewScreen: false, hasViewedReviewScreen: false,
hasSubmittedHoldToSwap: false, hasSubmittedHoldToSwap: false,
hasSkippedUnitagPrompt: false, hasSkippedUnitagPrompt: false,
hasCompletedUnitagsIntroModal: false,
} }
const slice = createSlice({ const slice = createSlice({
...@@ -29,10 +31,17 @@ const slice = createSlice({ ...@@ -29,10 +31,17 @@ const slice = createSlice({
setHasSkippedUnitagPrompt: (state, action: PayloadAction<boolean>) => { setHasSkippedUnitagPrompt: (state, action: PayloadAction<boolean>) => {
state.hasSkippedUnitagPrompt = action.payload state.hasSkippedUnitagPrompt = action.payload
}, },
setHasCompletedUnitagsIntroModal: (state, action: PayloadAction<boolean>) => {
state.hasCompletedUnitagsIntroModal = action.payload
},
}, },
}) })
export const { setHasViewedReviewScreen, setHasSubmittedHoldToSwap, setHasSkippedUnitagPrompt } = export const {
slice.actions setHasViewedReviewScreen,
setHasSubmittedHoldToSwap,
setHasSkippedUnitagPrompt,
setHasCompletedUnitagsIntroModal,
} = slice.actions
export const behaviorHistoryReducer = slice.reducer export const behaviorHistoryReducer = slice.reducer
...@@ -10,8 +10,15 @@ import { ...@@ -10,8 +10,15 @@ import {
State, State,
} from 'react-native-gesture-handler' } from 'react-native-gesture-handler'
import { useAnimatedStyle, useSharedValue, withDelay, withSpring } from 'react-native-reanimated' import { useAnimatedStyle, useSharedValue, withDelay, withSpring } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import {
import { AnimatedFlex, Flex, Text, TouchableArea, mediumShadowProps, useDeviceInsets } from 'ui/src' AnimatedFlex,
Flex,
Text,
TouchableArea,
isWeb,
mediumShadowProps,
useDeviceInsets,
} from 'ui/src'
import { borderRadii, spacing } from 'ui/src/theme' import { borderRadii, spacing } from 'ui/src/theme'
import { useTimeout } from 'utilities/src/time/timing' import { useTimeout } from 'utilities/src/time/timing'
import { selectActiveAccountNotifications } from 'wallet/src/features/notifications/selectors' import { selectActiveAccountNotifications } from 'wallet/src/features/notifications/selectors'
......
import { isWeb } from 'tamagui' import { Flex, Icons, Shine, Skeleton, Text, isWeb, useSporeColors } from 'ui/src'
import { Flex, Icons, Shine, Skeleton, Text, useSporeColors } from 'ui/src'
import { isWarmLoadingStatus } from 'wallet/src/data/utils' import { isWarmLoadingStatus } from 'wallet/src/data/utils'
import { usePortfolioTotalValue } from 'wallet/src/features/dataApi/balances' import { usePortfolioTotalValue } from 'wallet/src/features/dataApi/balances'
type WalletBalanceProps = { type WalletBalanceProps = {
......
import { ImpactFeedbackStyle } from 'expo-haptics' import { ImpactFeedbackStyle } from 'expo-haptics'
import { memo } from 'react' import { memo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { Flex, Shine, Text, TouchableArea, isWeb } from 'ui/src'
import { Flex, Shine, Text, TouchableArea } from 'ui/src'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { TokenLogo } from 'wallet/src/components/CurrencyLogo/TokenLogo' import { TokenLogo } from 'wallet/src/components/CurrencyLogo/TokenLogo'
import { RelativeChange } from 'wallet/src/components/text/RelativeChange' import { RelativeChange } from 'wallet/src/components/text/RelativeChange'
......
...@@ -8,7 +8,6 @@ import { ...@@ -8,7 +8,6 @@ import {
Platform, Platform,
TextInputFocusEventData, TextInputFocusEventData,
} from 'react-native' } from 'react-native'
import { isWeb } from 'tamagui'
import { import {
AnimatePresence, AnimatePresence,
Button, Button,
...@@ -19,6 +18,7 @@ import { ...@@ -19,6 +18,7 @@ import {
SpaceTokens, SpaceTokens,
Text, Text,
TouchableArea, TouchableArea,
isWeb,
useDeviceDimensions, useDeviceDimensions,
} from 'ui/src' } from 'ui/src'
import { fonts, iconSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, spacing } from 'ui/src/theme'
......
...@@ -2,8 +2,7 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' ...@@ -2,8 +2,7 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FadeInUp, FadeOut } from 'react-native-reanimated' import { FadeInUp, FadeOut } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import { AnimatedFlex, Button, Flex, isWeb, Text, useDeviceDimensions, useMedia } from 'ui/src'
import { AnimatedFlex, Button, Flex, Text, useDeviceDimensions, useMedia } from 'ui/src'
import { BackArrow } from 'ui/src/components/icons/BackArrow' import { BackArrow } from 'ui/src/components/icons/BackArrow'
import { fonts, iconSizes } from 'ui/src/theme' import { fonts, iconSizes } from 'ui/src/theme'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
......
import { FunctionComponent, useMemo } from 'react' import { FunctionComponent, useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { SvgProps } from 'react-native-svg' import { SvgProps } from 'react-native-svg'
import { isWeb } from 'tamagui' import { Icons, isWeb } from 'ui/src'
import { Icons } from 'ui/src'
import { useSwapFormContext } from 'wallet/src/features/transactions/contexts/SwapFormContext' import { useSwapFormContext } from 'wallet/src/features/transactions/contexts/SwapFormContext'
import { useSwapTxContext } from 'wallet/src/features/transactions/contexts/SwapTxContext' import { useSwapTxContext } from 'wallet/src/features/transactions/contexts/SwapTxContext'
import { useSwapWarnings } from 'wallet/src/features/transactions/hooks/useSwapWarnings' import { useSwapWarnings } from 'wallet/src/features/transactions/hooks/useSwapWarnings'
......
...@@ -2,7 +2,7 @@ import { useNetInfo } from '@react-native-community/netinfo' ...@@ -2,7 +2,7 @@ import { useNetInfo } from '@react-native-community/netinfo'
import { Percent } from '@uniswap/sdk-core' import { Percent } from '@uniswap/sdk-core'
import _ from 'lodash' import _ from 'lodash'
import { TFunction } from 'react-i18next' import { TFunction } from 'react-i18next'
import { isWeb } from 'tamagui' import { isWeb } from 'ui/src'
import { formatPriceImpact } from 'utilities/src/format/formatPriceImpact' import { formatPriceImpact } from 'utilities/src/format/formatPriceImpact'
import { useMemoCompare } from 'utilities/src/react/hooks' import { useMemoCompare } from 'utilities/src/react/hooks'
import { import {
......
import { CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core' import { CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { isWeb } from 'ui/src'
import { useOnChainNativeCurrencyBalance } from 'wallet/src/features/portfolio/api' import { useOnChainNativeCurrencyBalance } from 'wallet/src/features/portfolio/api'
import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types' import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types'
import { CurrencyField } from 'wallet/src/features/transactions/transactionState/types' import { CurrencyField } from 'wallet/src/features/transactions/transactionState/types'
......
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { Keyboard } from 'react-native' import { Keyboard } from 'react-native'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import { AnimatedFlex, Flex, Icons, isWeb, Text, TouchableArea, useSporeColors } from 'ui/src'
import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { useUSDValue } from 'wallet/src/features/gas/hooks' import { useUSDValue } from 'wallet/src/features/gas/hooks'
......
import { Dispatch, ReactNode, SetStateAction, useEffect, useState } from 'react' import { Dispatch, ReactNode, SetStateAction, useEffect, useState } from 'react'
import { isWeb } from 'tamagui' import { isWeb } from 'ui/src'
import { Trace } from 'utilities/src/telemetry/trace/Trace' import { Trace } from 'utilities/src/telemetry/trace/Trace'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants' import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants'
......
/* eslint-disable complexity */ /* eslint-disable complexity */
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { TFunction, useTranslation } from 'react-i18next' import { TFunction, useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { Button, Flex, Icons, Text, isWeb } from 'ui/src'
import { Button, Flex, Icons, Text } from 'ui/src'
import { Trace } from 'utilities/src/telemetry/trace/Trace' import { Trace } from 'utilities/src/telemetry/trace/Trace'
import { import {
selectHasSubmittedHoldToSwap, selectHasSubmittedHoldToSwap,
......
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard } from 'react-native' import { Keyboard } from 'react-native'
import { isWeb } from 'tamagui' import { Flex, Icons, isWeb, Text, TouchableArea, useSporeColors } from 'ui/src'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src'
import EyeIcon from 'ui/src/assets/icons/eye.svg' import EyeIcon from 'ui/src/assets/icons/eye.svg'
import SettingsIcon from 'ui/src/assets/icons/settings.svg' import SettingsIcon from 'ui/src/assets/icons/settings.svg'
import XIcon from 'ui/src/assets/icons/x.svg' import XIcon from 'ui/src/assets/icons/x.svg'
......
...@@ -11,8 +11,7 @@ import { ...@@ -11,8 +11,7 @@ import {
useDerivedValue, useDerivedValue,
withTiming, withTiming,
} from 'react-native-reanimated' } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import { AnimatedFlex, Flex, Icons, Text, TouchableArea, isWeb, useSporeColors } from 'ui/src'
import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src'
import { iconSizes, spacing } from 'ui/src/theme' import { iconSizes, spacing } from 'ui/src/theme'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { Trace } from 'utilities/src/telemetry/trace/Trace' import { Trace } from 'utilities/src/telemetry/trace/Trace'
......
...@@ -26,8 +26,7 @@ import { ...@@ -26,8 +26,7 @@ import {
import { OnShowSwapFeeInfo } from 'wallet/src/features/transactions/TransactionDetails/SwapFee' import { OnShowSwapFeeInfo } from 'wallet/src/features/transactions/TransactionDetails/SwapFee'
import { ElementName, ModalName } from 'wallet/src/telemetry/constants' import { ElementName, ModalName } from 'wallet/src/telemetry/constants'
import { isWeb } from 'tamagui' import { AnimatedFlex, Button, Flex, isWeb, Separator } from 'ui/src'
import { AnimatedFlex, Button, Flex, Separator } from 'ui/src'
import { BackArrow } from 'ui/src/components/icons/BackArrow' import { BackArrow } from 'ui/src/components/icons/BackArrow'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
......
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { useCallback } from 'react' import { useCallback } from 'react'
import { isWeb } from 'tamagui' import { isWeb } from 'ui/src'
import { flowToModalName } from 'wallet/src/components/TokenSelector/flowToModalName' import { flowToModalName } from 'wallet/src/components/TokenSelector/flowToModalName'
import { import {
TokenSelector, TokenSelector,
......
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isWeb } from 'tamagui' import { Button, Flex, Icons, Text, isWeb, useSporeColors } from 'ui/src'
import { Button, Flex, Icons, Text, useSporeColors } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { CurrencyLogo } from 'wallet/src/components/CurrencyLogo/CurrencyLogo' import { CurrencyLogo } from 'wallet/src/components/CurrencyLogo/CurrencyLogo'
......
...@@ -5,8 +5,16 @@ import { impactAsync } from 'expo-haptics' ...@@ -5,8 +5,16 @@ import { impactAsync } from 'expo-haptics'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated' import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated'
import { isWeb } from 'tamagui' import {
import { AnimatedFlex, Button, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' AnimatedFlex,
Button,
Flex,
Icons,
Text,
TouchableArea,
isWeb,
useSporeColors,
} from 'ui/src'
import AlertTriangleIcon from 'ui/src/assets/icons/alert-triangle.svg' import AlertTriangleIcon from 'ui/src/assets/icons/alert-triangle.svg'
import { fonts, iconSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, spacing } from 'ui/src/theme'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
......
import { providers } from 'ethers' import { providers } from 'ethers'
import { Statsig } from 'statsig-react-native' import { Statsig } from 'statsig-react-native'
import { isWeb } from 'tamagui'
import { call, select } from 'typed-redux-saga' import { call, select } from 'typed-redux-saga'
import { isWeb } from 'ui/src'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { RPCType } from 'wallet/src/constants/chains' import { RPCType } from 'wallet/src/constants/chains'
import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants' import { FEATURE_FLAGS } from 'wallet/src/features/experiments/constants'
......
...@@ -5,7 +5,6 @@ import React, { useCallback, useEffect, useState } from 'react' ...@@ -5,7 +5,6 @@ import React, { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard, LayoutChangeEvent, StyleSheet } from 'react-native' import { Keyboard, LayoutChangeEvent, StyleSheet } from 'react-native'
import { FadeIn, FadeOut, FadeOutDown } from 'react-native-reanimated' import { FadeIn, FadeOut, FadeOutDown } from 'react-native-reanimated'
import { isWeb } from 'tamagui'
import { import {
AnimatedFlex, AnimatedFlex,
Button, Button,
...@@ -13,6 +12,7 @@ import { ...@@ -13,6 +12,7 @@ import {
Icons, Icons,
Text, Text,
TouchableArea, TouchableArea,
isWeb,
useDeviceDimensions, useDeviceDimensions,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
"{{what}} to {{recipient}}": "{{what}} to {{recipient}}", "{{what}} to {{recipient}}": "{{what}} to {{recipient}}",
"<0>Allow {dapp.name} to use up to<3> {readablePermitAmount} </3>{permitCurrency?.symbol}?</0>": "<0>Allow {dapp.name} to use up to<3> {readablePermitAmount} </3>{permitCurrency?.symbol}?</0>", "<0>Allow {dapp.name} to use up to<3> {readablePermitAmount} </3>{permitCurrency?.symbol}?</0>": "<0>Allow {dapp.name} to use up to<3> {readablePermitAmount} </3>{permitCurrency?.symbol}?</0>",
"<0>Allow <1>{dapp.name}</1> to use your {permitCurrency?.symbol}?</0>": "<0>Allow <1>{dapp.name}</1> to use your {permitCurrency?.symbol}?</0>", "<0>Allow <1>{dapp.name}</1> to use your {permitCurrency?.symbol}?</0>": "<0>Allow <1>{dapp.name}</1> to use your {permitCurrency?.symbol}?</0>",
"<0>This isn’t your currently active wallet.</0><1>Make sure it’s the right one</1>": "<0>This isn’t your currently active wallet.</0><1>Make sure it’s the right one</1>",
"<0>You need more <2>{{currencySymbol}}</2> to cover the network cost for this transaction.</0>": "<0>You need more <2>{{currencySymbol}}</2> to cover the network cost for this transaction.</0>", "<0>You need more <2>{{currencySymbol}}</2> to cover the network cost for this transaction.</0>": "<0>You need more <2>{{currencySymbol}}</2> to cover the network cost for this transaction.</0>",
"<0>You’re removing <2>{{wallet}}</2></0>": "<0>You’re removing <2>{{wallet}}</2></0>", "<0>You’re removing <2>{{wallet}}</2></0>": "<0>You’re removing <2>{{wallet}}</2></0>",
"<0>You’re removing your <2>recovery phrase</2></0>": "<0>You’re removing your <2>recovery phrase</2></0>", "<0>You’re removing your <2>recovery phrase</2></0>": "<0>You’re removing your <2>recovery phrase</2></0>",
...@@ -629,7 +630,6 @@ ...@@ -629,7 +630,6 @@
"This address is blocked on Uniswap Wallet because it is associated with one or more blocked activities. If you believe this is an error, please email compliance@uniswap.org.": "This address is blocked on Uniswap Wallet because it is associated with one or more blocked activities. If you believe this is an error, please email compliance@uniswap.org.", "This address is blocked on Uniswap Wallet because it is associated with one or more blocked activities. If you believe this is an error, please email compliance@uniswap.org.": "This address is blocked on Uniswap Wallet because it is associated with one or more blocked activities. If you believe this is an error, please email compliance@uniswap.org.",
"This is a {text.toLowerCase()} password": "This is a {text.toLowerCase()} password", "This is a {text.toLowerCase()} password": "This is a {text.toLowerCase()} password",
"This is a view-only wallet": "This is a view-only wallet", "This is a view-only wallet": "This is a view-only wallet",
"This is not your active wallet": "This is not your active wallet",
"This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.": "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.", "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.": "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.",
"This is your personal space for tokens, NFTs, and all of your trades. Finish setting it up to keep your funds safe.": "This is your personal space for tokens, NFTs, and all of your trades. Finish setting it up to keep your funds safe.", "This is your personal space for tokens, NFTs, and all of your trades. Finish setting it up to keep your funds safe.": "This is your personal space for tokens, NFTs, and all of your trades. Finish setting it up to keep your funds safe.",
"This is your unique name that anyone can send crypto to.": "This is your unique name that anyone can send crypto to.", "This is your unique name that anyone can send crypto to.": "This is your unique name that anyone can send crypto to.",
......
...@@ -109,8 +109,7 @@ ...@@ -109,8 +109,7 @@
"./apps/next/.next/**" "./apps/next/.next/**"
], ],
"dependsOn": [ "dependsOn": [
"^build", "^build"
"utilities#typecheck"
] ]
}, },
"storybook#build": { "storybook#build": {
......
...@@ -44895,7 +44895,6 @@ __metadata: ...@@ -44895,7 +44895,6 @@ __metadata:
redux-saga: 1.2.2 redux-saga: 1.2.2
redux-saga-test-plan: 4.0.4 redux-saga-test-plan: 4.0.4
statsig-react-native: 4.11.0 statsig-react-native: 4.11.0
tamagui: 1.89.26
typechain: 5.2.0 typechain: 5.2.0
typed-redux-saga: 1.5.0 typed-redux-saga: 1.5.0
typescript: 5.3.3 typescript: 5.3.3
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment