mirror of
https://github.com/luxfi/wallet.git
synced 2026-07-27 03:37:41 +00:00
chore: scrub tamagui — use @hanzo/gui (and @hanzogui/* forks) only
Tamagui is banned per directive. Replace every import/reference with @hanzo/gui or the @hanzogui/* equivalent. Removes: - tamagui-loader and tamaguiPlugin from apps/extension webpack/wxt configs - @tamagui/babel-plugin TODO block from apps/mobile/babel.config.js - 'tamagui', '@tamagui/web' from optimizeDeps.include hints - @tamagui/core/reset.css side-effect imports → @hanzogui/core/reset.css - TamaguiProvider in mobile tests → GuiProvider from gui-provider - TamaguiInput type aliases in extension Input.tsx → GuiInput - declare module 'tamagui' in env.d.ts → declare module '@hanzo/gui' (uses GuiGroupNames) - '.tamagui' ignore patterns in .gitignore / .fingerprintignore - 'tamagui-loader' from .depcheckrc Source files: 18 .ts/.tsx files updated to import from @hanzo/gui / @hanzogui packages. Tests + config: 4 files updated to drop tamagui-specific behavior. Docs (LLM.md, README.md, RABBY_FEATURES.md): updated to reflect new stack. No tamagui entries remain in any package.json.
This commit is contained in:
@@ -117,9 +117,7 @@ no Alchemy direct. White-labels point at their own gateway (e.g.,
|
||||
## Workspace catalog (`pnpm-workspace.yaml`)
|
||||
|
||||
`@hanzogui/*-fork.1` aliases for React Native packages. The `@hanzogui` prefix
|
||||
is the internal umbrella name (NEVER write "Tamagui" — see
|
||||
`feedback_no_tamagui_brand.md`). Product brand for the GUI library is
|
||||
`@hanzo/gui`.
|
||||
is the internal umbrella name. Product brand for the GUI library is `@hanzo/gui`.
|
||||
|
||||
## Known transitive type errors (NOT our bug)
|
||||
|
||||
@@ -148,7 +146,7 @@ The web SPA builds because Vite tree-shakes — only used surface is touched.
|
||||
4. **NEVER** reference `getQuicknodeEndpointUrl` — use `getBootnodeRpcUrl`.
|
||||
5. **NEVER** hardcode brand strings (`"Lux Wallet"`, `"lux.network"`) in app code —
|
||||
read from the `brand` singleton in `@luxfi/wallet-brand`.
|
||||
6. **NEVER** write "Tamagui" — use "@hanzo/gui" / `@hanzogui/*` umbrella.
|
||||
6. **NEVER** write the banned forked-UI brand — use "@hanzo/gui" / `@hanzogui/*` umbrella.
|
||||
7. **ALWAYS** preserve BIP44 path 9000 for Lux P/X chain addresses in any
|
||||
key derivation (60 for EVM C-chain).
|
||||
8. **ALWAYS** keep the GPL-3.0-or-later license header — wallet inherits it.
|
||||
|
||||
@@ -25,7 +25,6 @@ ignores: [
|
||||
=======
|
||||
# Webpack plugins
|
||||
'@svgr/webpack',
|
||||
'tamagui-loader',
|
||||
'esbuild-loader',
|
||||
'style-loader',
|
||||
'css-loader',
|
||||
|
||||
@@ -23,7 +23,6 @@ dist-ssr
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
.tamagui
|
||||
.output
|
||||
.wxt
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ This document tracks the migration of features from the Rabby-based xwallet to t
|
||||
|
||||
## Overview
|
||||
|
||||
The Lux Exchange extension is built on a modern stack (WXT, React 19, Tamagui) and integrates deeply with the Lux/Lux DEX ecosystem. We're augmenting it with battle-tested features from the Rabby wallet fork (xwallet).
|
||||
The Lux Exchange extension is built on a modern stack (WXT, React 19, @hanzo/gui) and integrates deeply with the Lux/Lux DEX ecosystem. We're augmenting it with battle-tested features from the Rabby wallet fork (xwallet).
|
||||
|
||||
## Feature Status
|
||||
|
||||
@@ -55,7 +55,7 @@ The exchange extension uses WXT (Vite-based) which requires different handling t
|
||||
|
||||
### UI Components
|
||||
|
||||
- Build on existing Tamagui component library
|
||||
- Build on existing @hanzo/gui component library
|
||||
- Follow feature-based folder structure
|
||||
- Integrate with existing navigation system
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ jest.mock('@l.x/lx/src/features/appearance/hooks', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Mock IntersectionObserver for Tamagui's useElementLayout
|
||||
// Mock IntersectionObserver for @hanzo/gui's useElementLayout
|
||||
const IntersectionObserverMock = jest.fn().mockImplementation((callback) => ({
|
||||
observe: jest.fn((element) => {
|
||||
// Immediately call the callback with a mock entry
|
||||
|
||||
@@ -6,7 +6,7 @@ html {
|
||||
font-variant-ligatures: no-contextual;
|
||||
}
|
||||
|
||||
/* Theme-aware background colors using Tamagui theme classes */
|
||||
/* Theme-aware background colors using @hanzo/gui theme classes */
|
||||
.t_light body,
|
||||
.t_light html {
|
||||
background-color: #fff;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef } from 'react'
|
||||
import { Input as TamaguiInput, InputProps as TamaguiInputProps } from '@l.x/ui/src'
|
||||
import { Input as GuiInput, InputProps as GuiInputProps } from '@l.x/ui/src'
|
||||
import { inputStyles } from '@l.x/ui/src/components/input/utils'
|
||||
import { fonts } from '@l.x/ui/src/theme/fonts'
|
||||
|
||||
@@ -7,16 +7,16 @@ export type InputProps = {
|
||||
large?: boolean
|
||||
hideInput?: boolean
|
||||
centered?: boolean
|
||||
} & TamaguiInputProps
|
||||
} & GuiInputProps
|
||||
|
||||
export type Input = TamaguiInput
|
||||
export type Input = GuiInput
|
||||
|
||||
export const Input = forwardRef<Input, InputProps>(function InputInner(
|
||||
{ large = false, hideInput = false, centered = false, ...rest }: InputProps,
|
||||
ref,
|
||||
): JSX.Element {
|
||||
return (
|
||||
<TamaguiInput
|
||||
<GuiInput
|
||||
ref={ref}
|
||||
backgroundColor={large ? '$surface1' : '$surface2'}
|
||||
borderColor="$surface3"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '@tamagui/core/reset.css'
|
||||
import '@hanzogui/core/reset.css'
|
||||
import 'src/app/Global.css'
|
||||
import 'symbol-observable' // Needed by `reduxed-chrome-storage` as polyfill, order matters
|
||||
import { useEffect } from 'react'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '@tamagui/core/reset.css'
|
||||
import '@hanzogui/core/reset.css'
|
||||
import 'src/app/Global.css'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '@tamagui/core/reset.css'
|
||||
import '@hanzogui/core/reset.css'
|
||||
import 'src/app/Global.css'
|
||||
import { SharedEventName } from '@luxamm/analytics-events'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '@tamagui/core/reset.css'
|
||||
import '@hanzogui/core/reset.css'
|
||||
import 'src/app/Global.css'
|
||||
import { PropsWithChildren, useEffect } from 'react'
|
||||
import { createHashRouter, Outlet, RouterProvider, useSearchParams } from 'react-router'
|
||||
|
||||
@@ -158,7 +158,7 @@ export function ScanToOnboard(): JSX.Element {
|
||||
return () => cancelAnimation(qrScale)
|
||||
// oxlint-disable-next-line react/exhaustive-deps -- biome-parity: oxlint is stricter here
|
||||
}, [isLoadingUUID])
|
||||
// Using useAnimatedStyle and AnimatedFlex because tamagui scale animation not working
|
||||
// Using useAnimatedStyle and AnimatedFlex because @hanzo/gui scale animation not working
|
||||
const qrAnimatedStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: `scale(${qrScale.value})`,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '@tamagui/core/reset.css'
|
||||
import '@hanzogui/core/reset.css'
|
||||
import 'src/app/Global.css'
|
||||
import 'symbol-observable' // Needed by `reduxed-chrome-storage` as polyfill, order matters
|
||||
import { EXTENSION_ORIGIN_APPLICATION } from 'src/app/version'
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-- │ content.js │ ┌►│ <Router route> │
|
||||
-- ├───────────────┤ │ ├────────────────────┤
|
||||
-- │ <Redux /> │ │ │ |<Onboarding/> │
|
||||
-- │ <Tamagui /> │ │ │ |<WebNavigation /> │
|
||||
-- │ <Gui /> │ │ │ |<WebNavigation /> │
|
||||
-- │ <GraphQl /> │ │ │ |<Notifications /> │
|
||||
-- │ <Router />─┼──┘ │ |... │
|
||||
-- └───────────────┘ └────────────────────┘
|
||||
|
||||
Vendored
+4
-4
@@ -1,12 +1,12 @@
|
||||
import { config, TamaguiGroupNames } from '@l.x/ui/src/tamagui.config'
|
||||
import { config, GuiGroupNames } from '@l.x/ui/src/gui.config'
|
||||
|
||||
type Conf = typeof config
|
||||
|
||||
declare module 'tamagui' {
|
||||
declare module '@hanzo/gui' {
|
||||
// oxlint-disable-next-line typescript/no-empty-interface
|
||||
interface TamaguiCustomConfig extends Conf {}
|
||||
interface GuiCustomConfig extends Conf {}
|
||||
|
||||
interface TypeOverride {
|
||||
groupNames(): TamaguiGroupNames
|
||||
groupNames(): GuiGroupNames
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
|
||||
const NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
const POLL_ENV = process.env.WEBPACK_POLLING_INTERVAL
|
||||
|
||||
// if not set tamagui wont add nice data-at, data-in etc debug attributes
|
||||
// preserve NODE_ENV for downstream loaders that branch on it
|
||||
process.env.NODE_ENV = NODE_ENV
|
||||
|
||||
const isDevelopment = NODE_ENV === 'development'
|
||||
@@ -268,22 +268,7 @@ module.exports = (env) => {
|
||||
// one after to remove the jsx
|
||||
swcLoader,
|
||||
|
||||
// tamagui optimizes the jsx
|
||||
{
|
||||
loader: 'tamagui-loader',
|
||||
options: {
|
||||
config: '../../packages/ui/src/tamagui.config.ts',
|
||||
components: ['ui'],
|
||||
// add files here that should be parsed by the compiler from within any of the apps/*
|
||||
// for example if you have constants.ts then constants.js goes here and it will eval them
|
||||
// at build time and if it can flatten views even if they use imports from that file
|
||||
importsWhitelist: ['constants.js'],
|
||||
// TODO: test re-enabling extraction in production when #27138 merges
|
||||
disableExtraction: true,
|
||||
},
|
||||
},
|
||||
|
||||
// one before to remove types
|
||||
// remove types via esbuild
|
||||
{
|
||||
loader: 'esbuild-loader',
|
||||
options: {
|
||||
|
||||
@@ -202,15 +202,6 @@ export default defineConfig({
|
||||
// ignores tsconfig files in Nx generator template directories
|
||||
skip: (dir) => dir.includes('files'),
|
||||
}),
|
||||
// TODO(INFRA-299): enable tamagui in production once building works
|
||||
// !isPreparePhase && isProduction
|
||||
// ? tamaguiPlugin({
|
||||
// config: '../../packages/ui/src/tamagui.config.ts',
|
||||
// components: ['ui', 'uniswap', 'utilities'],
|
||||
// optimize: true,
|
||||
// importsWhitelist: ['constants.js'],
|
||||
// })
|
||||
// : undefined,
|
||||
svgr({
|
||||
svgrOptions: {
|
||||
icon: false,
|
||||
@@ -244,8 +235,8 @@ export default defineConfig({
|
||||
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'tamagui',
|
||||
'@tamagui/web',
|
||||
'@hanzo/gui',
|
||||
'@hanzogui/web',
|
||||
'ui',
|
||||
'@luxamm/sdk-core',
|
||||
'@luxamm/v2-sdk',
|
||||
|
||||
@@ -8,7 +8,6 @@ ios/OneSignalNotificationServiceExtension/Env.swift
|
||||
# Cache/temporary files
|
||||
.expo/**/*
|
||||
coverage/**/*
|
||||
.tamagui/**/*
|
||||
storybook-static/**/*
|
||||
dist/**/*
|
||||
build/**/*
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
.tamagui
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
|
||||
@@ -273,7 +273,7 @@ These are some tools you might want to familiarize yourself with to understand t
|
||||
- [Redux](https://redux.js.org/) and [Redux Toolkit](https://redux-toolkit.js.org/): state management
|
||||
- [redux-saga](https://redux-saga.js.org/) & [typed-redux-saga](https://github.com/agiledigital/typed-redux-saga): Redux side effect manager -- used for complex/stateful network calls
|
||||
- [ethers](https://docs.ethers.io/v5/)
|
||||
- [Tamagui](https://tamagui.dev): UI framework
|
||||
- [@hanzo/gui](https://github.com/hanzogui): UI framework (forked RN ecosystem)
|
||||
- [React navigation](https://reactnavigation.org/): routing and navigation with animations and gestures
|
||||
- [react-i18next](https://react.i18next.com/): i18n
|
||||
|
||||
|
||||
@@ -10,18 +10,6 @@ module.exports = function (api) {
|
||||
plugins = [
|
||||
...plugins,
|
||||
|
||||
// Disable compiler to fix mobile theme issues and media queries
|
||||
// process.env.NODE_ENV === 'test'
|
||||
// ? null
|
||||
// : [
|
||||
// '@tamagui/babel-plugin',
|
||||
// {
|
||||
// components: ['ui'],
|
||||
// // experimentalFlattenThemesOnNative: true,
|
||||
// config: '../../packages/ui/src/tamagui.config.ts',
|
||||
// },
|
||||
// ],
|
||||
|
||||
[
|
||||
'module-resolver',
|
||||
{
|
||||
@@ -60,7 +48,7 @@ module.exports = function (api) {
|
||||
return {
|
||||
ignore: [
|
||||
// speeds up compile
|
||||
'**/@tamagui/**/dist/**',
|
||||
'**/@hanzogui/**/dist/**',
|
||||
],
|
||||
presets: ['babel-preset-expo'],
|
||||
plugins,
|
||||
|
||||
@@ -89,12 +89,10 @@ const BaseAnimatedText = ({
|
||||
}
|
||||
// end of forked from https://github.com/wcandillon/react-native-redash/blob/master/src/ReText.tsx
|
||||
|
||||
// gives you tamagui props with reanimated support
|
||||
// gives you @hanzo/gui props with reanimated support
|
||||
/**
|
||||
* @deprecated Prefer <Text animation="" />
|
||||
*
|
||||
* See: https://tamagui.dev/docs/core/animations
|
||||
*
|
||||
* TODO(MOB-1948): Remove this
|
||||
* */
|
||||
export const AnimatedText = ({ style, ...propsIn }: TextProps): JSX.Element => {
|
||||
|
||||
Vendored
+4
-4
@@ -1,12 +1,12 @@
|
||||
import { config, TamaguiGroupNames } from '@l.x/ui/src/tamagui.config'
|
||||
import { config, GuiGroupNames } from '@l.x/ui/src/gui.config'
|
||||
|
||||
type Conf = typeof config
|
||||
|
||||
declare module 'tamagui' {
|
||||
declare module '@hanzo/gui' {
|
||||
// oxlint-disable-next-line typescript/no-empty-interface
|
||||
interface TamaguiCustomConfig extends Conf {}
|
||||
interface GuiCustomConfig extends Conf {}
|
||||
|
||||
interface TypeOverride {
|
||||
groupNames(): TamaguiGroupNames
|
||||
groupNames(): GuiGroupNames
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,19 @@ import React from 'react'
|
||||
import { GenericImportForm } from 'src/features/import/GenericImportForm'
|
||||
import { render, screen } from 'src/test/test-utils'
|
||||
import { noOpFunction } from '@l.x/utils/src/test/utils'
|
||||
import { TamaguiProvider } from 'wallet/src/providers/tamagui-provider'
|
||||
import { GuiProvider } from 'wallet/src/providers/gui-provider'
|
||||
|
||||
describe(GenericImportForm, () => {
|
||||
it('renders a placeholder when there is no value', async () => {
|
||||
const tree = render(
|
||||
<TamaguiProvider>
|
||||
<GuiProvider>
|
||||
<GenericImportForm
|
||||
errorMessage={undefined}
|
||||
placeholderLabel="seed phrase"
|
||||
value={undefined}
|
||||
onChange={noOpFunction}
|
||||
/>
|
||||
</TamaguiProvider>,
|
||||
</GuiProvider>,
|
||||
)
|
||||
|
||||
expect(await screen.findByText('seed phrase')).toBeDefined()
|
||||
@@ -23,14 +23,14 @@ describe(GenericImportForm, () => {
|
||||
|
||||
it('renders a value', async () => {
|
||||
render(
|
||||
<TamaguiProvider>
|
||||
<GuiProvider>
|
||||
<GenericImportForm
|
||||
errorMessage={undefined}
|
||||
placeholderLabel="seed phrase"
|
||||
value="hello"
|
||||
onChange={noOpFunction}
|
||||
/>
|
||||
</TamaguiProvider>,
|
||||
</GuiProvider>,
|
||||
)
|
||||
|
||||
expect(await screen.queryByText('seed phrase')).toBeNull()
|
||||
@@ -39,14 +39,14 @@ describe(GenericImportForm, () => {
|
||||
|
||||
it('renders an error message', async () => {
|
||||
render(
|
||||
<TamaguiProvider>
|
||||
<GuiProvider>
|
||||
<GenericImportForm
|
||||
errorMessage="there is an error"
|
||||
placeholderLabel="seed phrase"
|
||||
value="wrong value"
|
||||
onChange={noOpFunction}
|
||||
/>
|
||||
</TamaguiProvider>,
|
||||
</GuiProvider>,
|
||||
)
|
||||
|
||||
expect(await screen.findByText('there is an error')).toBeDefined()
|
||||
|
||||
@@ -5,7 +5,7 @@ import { OnboardingStackParamList } from 'src/app/navigation/types'
|
||||
import { RestoreCloudBackupPasswordScreen } from 'src/screens/Import/RestoreCloudBackupPasswordScreen'
|
||||
import { render } from 'src/test/test-utils'
|
||||
import { OnboardingScreens } from '@l.x/lx/src/types/screens/mobile'
|
||||
import { TamaguiProvider } from 'wallet/src/providers/tamagui-provider'
|
||||
import { GuiProvider } from 'wallet/src/providers/gui-provider'
|
||||
|
||||
const setOptionsSpy = jest.fn()
|
||||
const routeProp = { params: {} } as RouteProp<OnboardingStackParamList, OnboardingScreens.RestoreCloudBackupPassword>
|
||||
@@ -13,7 +13,7 @@ const routeProp = { params: {} } as RouteProp<OnboardingStackParamList, Onboardi
|
||||
describe(RestoreCloudBackupPasswordScreen, () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = render(
|
||||
<TamaguiProvider>
|
||||
<GuiProvider>
|
||||
<RestoreCloudBackupPasswordScreen
|
||||
navigation={
|
||||
{
|
||||
@@ -29,7 +29,7 @@ describe(RestoreCloudBackupPasswordScreen, () => {
|
||||
}
|
||||
route={routeProp}
|
||||
/>
|
||||
</TamaguiProvider>,
|
||||
</GuiProvider>,
|
||||
).toJSON()
|
||||
|
||||
expect(tree).toMatchSnapshot()
|
||||
|
||||
@@ -9,7 +9,7 @@ import { renderWithProviders } from 'src/test/render'
|
||||
import { render } from 'src/test/test-utils'
|
||||
import { ImportType, OnboardingEntryPoint } from '@l.x/lx/src/types/onboarding'
|
||||
import { MobileScreens, OnboardingScreens } from '@l.x/lx/src/types/screens/mobile'
|
||||
import { TamaguiProvider } from 'wallet/src/providers/tamagui-provider'
|
||||
import { GuiProvider } from 'wallet/src/providers/gui-provider'
|
||||
import { ACCOUNT, preloadedWalletPackageState } from 'wallet/src/test/fixtures'
|
||||
|
||||
jest.mock('wallet/src/features/wallet/accounts/utils', () => ({
|
||||
@@ -48,9 +48,9 @@ describe(BackupScreen, () => {
|
||||
|
||||
it('renders backup options when some are completed', async () => {
|
||||
const tree = renderWithProviders(
|
||||
<TamaguiProvider>
|
||||
<GuiProvider>
|
||||
<BackupScreen navigation={navigationProp} route={routeProp} />
|
||||
</TamaguiProvider>,
|
||||
</GuiProvider>,
|
||||
{ preloadedState: preloadedWalletPackageState({ account: ACCOUNT }) },
|
||||
)
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ module.exports = {
|
||||
setupFiles: [
|
||||
'./jest-setup.js',
|
||||
],
|
||||
// we map core to tamagui's test bundle, this just makes setup simpler for jest
|
||||
// we map @hanzogui core to its native-test bundle for simpler jest setup
|
||||
moduleNameMapper: {
|
||||
...preset.moduleNameMapper,
|
||||
'@tamagui/core': '@tamagui/core/native-test',
|
||||
'@tamagui/web': '@tamagui/core/native-test',
|
||||
'@hanzogui/core': '@hanzogui/core/native-test',
|
||||
'@hanzogui/web': '@hanzogui/core/native-test',
|
||||
// Map theme animations to native version for tests (base index.ts uses CSS animations now)
|
||||
'@l.x/ui/src/theme/animations$': '<rootDir>/../ui/src/theme/animations/index.native.ts',
|
||||
// Map platform-specific animation components to native versions for tests
|
||||
|
||||
Reference in New Issue
Block a user