Skip to content

Commit

Permalink
Merge branch 'develop' into wallet-state-corruption-4
Browse files Browse the repository at this point in the history
  • Loading branch information
woodenfurniture authored Jan 9, 2025
2 parents 78f3ae8 + 2f3b30e commit 09e4b7d
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 140 deletions.
2 changes: 1 addition & 1 deletion .env.base
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ REACT_APP_FEATURE_SWAPPER_SOLANA=true

# Swapper feature flags - other .env files will override these
REACT_APP_FEATURE_CHAINFLIP_SWAP=true
REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=false
REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=true
REACT_APP_FEATURE_COWSWAP=true
REACT_APP_FEATURE_LIFI_SWAP=true
REACT_APP_FEATURE_THOR_SWAP=true
Expand Down
1 change: 0 additions & 1 deletion .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
REACT_APP_FEATURE_SWAPPER_SOLANA=true

# Swapper feature flags
REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=true
REACT_APP_FEATURE_LIMIT_ORDERS=true
REACT_APP_FEATURE_NEW_TRADE_FLOW=true

Expand Down
1 change: 0 additions & 1 deletion .env.develop
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
REACT_APP_FEATURE_SWAPPER_SOLANA=true

# Swapper feature flags
REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=true
REACT_APP_FEATURE_LIMIT_ORDERS=true
REACT_APP_FEATURE_NEW_TRADE_FLOW=true

Expand Down
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,18 @@
"@shapeshiftoss/caip": "workspace:^",
"@shapeshiftoss/chain-adapters": "workspace:^",
"@shapeshiftoss/errors": "workspace:^",
"@shapeshiftoss/hdwallet-coinbase": "1.57.1",
"@shapeshiftoss/hdwallet-core": "1.57.1",
"@shapeshiftoss/hdwallet-keepkey": "1.57.1",
"@shapeshiftoss/hdwallet-keepkey-webusb": "1.57.1",
"@shapeshiftoss/hdwallet-keplr": "1.57.1",
"@shapeshiftoss/hdwallet-ledger": "1.57.1",
"@shapeshiftoss/hdwallet-ledger-webusb": "1.57.1",
"@shapeshiftoss/hdwallet-metamask-multichain": "1.57.1",
"@shapeshiftoss/hdwallet-native": "1.57.1",
"@shapeshiftoss/hdwallet-native-vault": "1.57.1",
"@shapeshiftoss/hdwallet-phantom": "1.57.1",
"@shapeshiftoss/hdwallet-walletconnectv2": "1.57.1",
"@shapeshiftoss/hdwallet-coinbase": "1.58.0",
"@shapeshiftoss/hdwallet-core": "1.58.0",
"@shapeshiftoss/hdwallet-keepkey": "1.58.0",
"@shapeshiftoss/hdwallet-keepkey-webusb": "1.58.0",
"@shapeshiftoss/hdwallet-keplr": "1.58.0",
"@shapeshiftoss/hdwallet-ledger": "1.58.0",
"@shapeshiftoss/hdwallet-ledger-webusb": "1.58.0",
"@shapeshiftoss/hdwallet-metamask-multichain": "1.58.0",
"@shapeshiftoss/hdwallet-native": "1.58.0",
"@shapeshiftoss/hdwallet-native-vault": "1.58.0",
"@shapeshiftoss/hdwallet-phantom": "1.58.0",
"@shapeshiftoss/hdwallet-walletconnectv2": "1.58.0",
"@shapeshiftoss/swapper": "workspace:^",
"@shapeshiftoss/types": "workspace:^",
"@shapeshiftoss/unchained-client": "workspace:^",
Expand Down
16 changes: 14 additions & 2 deletions src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -1744,11 +1744,16 @@
},
"import": {
"header": "Import your wallet",
"keystoreHeader": "Import your keystore wallet",
"body": "Type or paste your Secret Recovery Phrase in all lower case with no commas or numbers and a single space between each word.",
"button": "Next",
"secretRecoveryPhraseError": "Enter your Secret Recovery Phrase with a single space in between words. Omit any commas, returns, or any additional characters.",
"secretRecoveryPhraseRequired": "Secret Recovery Phrase is required",
"secretRecoveryPhraseTooShort": "Secret Recovery Phrase is too short"
"secretRecoveryPhraseTooShort": "Secret Recovery Phrase is too short",
"dragAndDrop": "Drag & Drop or Choose File",
"keystoreImportBody": "Upload file by clicking browse or by dragging and dropping below.",
"importKeystore": "Import Keystore",
"invalidKeystorePassword": "Invalid keystore password"
},
"password": {
"header": "Create a New Password",
Expand All @@ -1766,10 +1771,17 @@
},
"start": {
"header": "ShapeShift Wallet",
"selectHeader": "Import Wallet",
"keystoreHeader": "Keystore Wallet",
"body": "You can have multiple ShapeShift wallets. You may load a wallet, import a wallet from a Secret Recovery Phrase, or create a new wallet.",
"selectBody": "Import wallet using your Secret Recovery Phrase or by uploading your keystore file.",
"import": "Import a wallet",
"secretRecoveryPhrase": "Secret Recovery Phrase",
"twelveWordSeedPhrase": "12 word seed phrase",
"keystore": "Keystore",
"create": "Create a new wallet",
"load": "Saved wallets"
"load": "Saved wallets",
"uploadKeystore": "Upload Keystore File"
},
"success": {
"encryptingWallet": "Encrypting your wallet... if your browser asks to store data in persistent storage, please click 'Allow'.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import {
Box,
Button,
FormControl,
FormErrorMessage,
Icon,
Input,
ModalBody,
ModalHeader,
Text as CText,
useColorModeValue,
VStack,
} from '@chakra-ui/react'
import { useCallback, useState } from 'react'
import type { FieldValues } from 'react-hook-form'
import { useForm } from 'react-hook-form'
import { FaFile } from 'react-icons/fa'
import { useTranslate } from 'react-polyglot'
import type { RouteComponentProps } from 'react-router-dom'
import { Text } from 'components/Text'
import { NativeWalletRoutes } from 'context/WalletProvider/types'
import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton'
import { MixPanelEvent } from 'lib/mixpanel/types'

import type { NativeWalletValues } from '../types'

const hoverSx = { borderColor: 'blue.500' }

// TODO(gomes): use https://www.chakra-ui.com/docs/components/file-upload if/when we migrate to chakra@3
const FileUpload = ({ onFileSelect }: { onFileSelect: (file: File) => void }) => {
const bgColor = useColorModeValue('gray.50', 'gray.800')
const borderColor = useColorModeValue('gray.200', 'gray.600')
const [isDragging, setIsDragging] = useState(false)
const [filename, setFilename] = useState<string | null>(null)

const handleDragEnter = useCallback((e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(true)
}, [])

const handleDragLeave = useCallback((e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(false)
}, [])

const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
}, [])

const processFile = useCallback(
(file: File) => {
setFilename(file.name)
onFileSelect(file)
},
[onFileSelect],
)

const handleDrop = useCallback(
(e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(false)

const files = e.dataTransfer.files
if (files?.[0]) {
processFile(files[0])
}
},
[processFile],
)

const handleFileInput = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files
if (files?.[0]) {
processFile(files[0])
}
},
[processFile],
)

return (
<FormControl>
<Input type='file' accept='.txt' onChange={handleFileInput} id='file-upload' display='none' />
<Box
as='label'
htmlFor='file-upload'
w='full'
h='32'
border='2px'
borderStyle='dashed'
borderColor={isDragging ? 'blue.500' : borderColor}
borderRadius='xl'
display='flex'
flexDirection='column'
alignItems='center'
justifyContent='center'
bg={bgColor}
cursor='pointer'
transition='all 0.2s'
_hover={hoverSx}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
<Icon as={FaFile} boxSize={6} color='gray.500' mb={2} />
{filename ? (
<CText color='gray.500'>{filename}</CText>
) : (
<Text color='gray.500' translation='walletProvider.shapeShift.import.dragAndDrop' />
)}
</Box>
</FormControl>
)
}

export const NativeImportKeystore = ({ history }: RouteComponentProps) => {
const [keystoreFile, setKeystoreFile] = useState<string | null>(null)
const mixpanel = getMixPanel()

const translate = useTranslate()

const {
setError,
handleSubmit,
formState: { errors, isSubmitting },
register,
} = useForm<NativeWalletValues>({ shouldUnregister: true })

const onSubmit = useCallback(
async (values: FieldValues) => {
const { Vault } = await import('@shapeshiftoss/hdwallet-native-vault')
const vault = await Vault.create()
vault.meta.set('createdAt', Date.now())

if (!keystoreFile) {
throw new Error('No keystore uploaded')
}

try {
await vault.loadFromKeystore(keystoreFile, values.keystorePassword)
} catch (e) {
setError('keystorePassword', {
type: 'manual',
message: translate('walletProvider.shapeShift.import.invalidKeystorePassword'),
})
return
}

history.push(NativeWalletRoutes.Password, { vault })
mixpanel?.track(MixPanelEvent.NativeImportKeystore)
},
[history, keystoreFile, mixpanel, setError, translate],
)

const handleFileSelect = useCallback((file: File) => {
const reader = new FileReader()
reader.onload = e => {
if (!e?.target) return
if (typeof e.target.result !== 'string') return
setKeystoreFile(e.target.result)
}
reader.readAsText(file)
}, [])

return (
<>
<ModalHeader>
<Text translation={'walletProvider.shapeShift.import.keystoreHeader'} />
</ModalHeader>
<ModalBody>
<Text
color='text.subtle'
mb={4}
translation='walletProvider.shapeShift.import.keystoreImportBody'
/>

<form onSubmit={handleSubmit(onSubmit)}>
<VStack spacing={6}>
<FileUpload onFileSelect={handleFileSelect} />

{keystoreFile && (
<>
<FormControl isInvalid={Boolean(errors.keystorePassword)}>
<Input
type='password'
placeholder='Keystore Password'
size='lg'
data-test='wallet-native-keystore-password'
{...register('keystorePassword')}
/>
<FormErrorMessage>{errors.keystorePassword?.message}</FormErrorMessage>
</FormControl>

<Button
colorScheme='blue'
width='full'
size='lg'
type='submit'
isLoading={isSubmitting}
data-test='wallet-native-keystore-submit'
>
<Text translation='walletProvider.shapeShift.import.importKeystore' />
</Button>
</>
)}
</VStack>
</form>
</ModalBody>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { MixPanelEvent } from 'lib/mixpanel/types'

import type { NativeWalletValues } from '../types'

export const NativeImport = ({ history }: RouteComponentProps) => {
export const NativeImportSeed = ({ history }: RouteComponentProps) => {
const mixpanel = getMixPanel()

const {
Expand All @@ -37,7 +37,7 @@ export const NativeImport = ({ history }: RouteComponentProps) => {
vault.meta.set('createdAt', Date.now())
vault.set('#mnemonic', values.mnemonic.toLowerCase().trim())
history.push(NativeWalletRoutes.Password, { vault })
mixpanel?.track(MixPanelEvent.NativeImport)
mixpanel?.track(MixPanelEvent.NativeImportSeed)
} catch (e) {
setError('mnemonic', { type: 'manual', message: 'walletProvider.shapeShift.import.header' })
}
Expand Down
Loading

0 comments on commit 09e4b7d

Please sign in to comment.