Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Commit

Permalink
Export address and contact metadata in QR code
Browse files Browse the repository at this point in the history
Related to #183
  • Loading branch information
nop33 committed Aug 8, 2023
1 parent 7b6718d commit 3a4138f
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 19 deletions.
2 changes: 1 addition & 1 deletion locales/bg-BG/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Преглед",
"Save": "Запази",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/de-DE/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Überprüfen",
"Save": "Speichern",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/en-US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@
"Review": "Review",
"Save": "Save",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/es-ES/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Comprobar",
"Save": "Guardar",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/fr-FR/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Vérification",
"Save": "Sauvegarder",
"Scan the blockchain for addresses you used in the past.": "Scannez la blockchain pour trouver des adresses utilisées par le passé.",
"Scan this QR code with your mobile wallet.": "Scannez ce code QR avec votre portefeuille mobile.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Chercher",
"Search for label, a hash or an asset...": "Cherchez un label, un hash ou un actif...",
"Search for name or a hash...": "Cherchez un nom ou un hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/id-ID/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Ulasan",
"Save": "Simpan",
"Scan the blockchain for addresses you used in the past.": "Pindai blockchain untuk alamat yang Anda gunakan sebelumnya.",
"Scan this QR code with your mobile wallet.": "Pindai kode QR ini dengan dompet seluler Anda.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Cari",
"Search for label, a hash or an asset...": "Telusuri untuk label, hash, atau aset...",
"Search for name or a hash...": "Telusuri untuk nama atau hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/pt-PT/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Rever",
"Save": "Guardar",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/ru-RU/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Обзор",
"Save": "Сохранить",
"Scan the blockchain for addresses you used in the past.": "Просканируйте блокчейн на наличие адресов, которые вы использовали в прошлом.",
"Scan this QR code with your mobile wallet.": "Отсканируйте этот QR-код с помощью своего мобильного кошелька.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Найти",
"Search for label, a hash or an asset...": "Поиск по имени, хэшу или активу...",
"Search for name or a hash...": "Поиск по имени или хэшу...",
Expand Down
2 changes: 1 addition & 1 deletion locales/tr-TR/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Gözden geçir",
"Save": "Kaydet",
"Scan the blockchain for addresses you used in the past.": "Scan the blockchain for addresses you used in the past.",
"Scan this QR code with your mobile wallet.": "Scan this QR code with your mobile wallet.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Search",
"Search for label, a hash or an asset...": "Search for label, a hash or an asset...",
"Search for name or a hash...": "Search for name or a hash...",
Expand Down
2 changes: 1 addition & 1 deletion locales/vi-VN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
"Review": "Xem lại",
"Save": "Lưu lại",
"Scan the blockchain for addresses you used in the past.": "Quét các địa chỉ trên blockchain mà bạn đã sử dụng trước đó.",
"Scan this QR code with your mobile wallet.": "Quét mã QR này bằng điện thoại của bạn.",
"Scan this animated QR code with your mobile wallet.": "Scan this animated QR code with your mobile wallet.",
"Search": "Tìm kiếm",
"Search for label, a hash or an asset...": "Tìm theo nhãn, hash hoặc tài sản...",
"Search for name or a hash...": "Tìm theo tên hoặc hash...",
Expand Down
85 changes: 85 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"nanoid": "^4.0.0",
"posthog-js": "^1.52.0",
"prettier": "^2.7.1",
"qrloop": "^1.4.1",
"react": "^18.2.0",
"react-apexcharts": "^1.4.0",
"react-color": "^2.19.3",
Expand Down
74 changes: 65 additions & 9 deletions src/modals/WalletQRCodeExportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,73 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.

import { encrypt } from '@alephium/sdk'
import { ScanLine } from 'lucide-react'
import { useState } from 'react'
import { dataToFrames } from 'qrloop'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import QRCode from 'react-qr-code'
import { useTheme } from 'styled-components'
import styled, { useTheme } from 'styled-components'

import InfoBox from '@/components/InfoBox'
import { Section } from '@/components/PageComponents/PageContainers'
import PasswordConfirmation from '@/components/PasswordConfirmation'
import { useAppSelector } from '@/hooks/redux'
import CenteredModal from '@/modals/CenteredModal'
import { selectAllAddresses, selectAllContacts } from '@/storage/addresses/addressesSelectors'

const FPS = 5

const WalletQRCodeExportModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation()
const theme = useTheme()
const activeWalletMnemonic = useAppSelector((state) => state.activeWallet.mnemonic)
const addresses = useAppSelector(selectAllAddresses)
const contacts = useAppSelector(selectAllContacts)

const [frames, setFrames] = useState<string[]>([])
const [frame, setFrame] = useState(0)

// Inspired by:
// - https://github.com/LedgerHQ/ledger-live/blob/edc7cc4091969564f8fe295ff2bf0a3e425a4ba6/apps/ledger-live-desktop/src/renderer/components/Exporter/QRCodeExporter.tsx
// - https://github.com/gre/qrloop/blob/06eaa7fd23bd27e0c638b1c66666cada1bbd0d30/examples/web-text-exporter
useEffect(() => {
let lastT: number
let requestedAnimationFrame: number

const loop = (t: number) => {
requestedAnimationFrame = requestAnimationFrame(loop)

if (!lastT) lastT = t

if ((t - lastT) * FPS < 1000) return

const [qrCodeTextToEncode, setQrCodeTextToEncode] = useState('')
lastT = t

setFrame((frame: number) => (frames.length > 0 ? (frame + 1) % frames.length : 0))
}

requestedAnimationFrame = requestAnimationFrame(loop)

return () => {
cancelAnimationFrame(requestedAnimationFrame)
}
}, [frames.length])

if (!activeWalletMnemonic) return null

const handleCorrectPasswordEntered = (password: string) => {
const encryptedDataToEncode = encrypt(password, activeWalletMnemonic, 'sha512')
const dataToEncrypt = {
mnemonic: activeWalletMnemonic,
addresses: addresses.map(({ index, label, color, isDefault }) => ({ index, label, color, isDefault })),
contacts: contacts.map(({ name, address }) => ({ name, address }))
}
const encryptedData = encrypt(password, JSON.stringify(dataToEncrypt), 'sha512')

setQrCodeTextToEncode(encryptedDataToEncode)
setFrames(dataToFrames(encryptedData, 160, 4))
}

return (
<CenteredModal title={t('Export wallet')} onClose={onClose} focusMode narrow={!qrCodeTextToEncode} skipFocusOnMount>
{!qrCodeTextToEncode ? (
<CenteredModal title={t('Export wallet')} onClose={onClose} focusMode narrow={frames.length === 0} skipFocusOnMount>
{frames.length === 0 ? (
<div>
<PasswordConfirmation
text={t('Type your password to export your wallet.')}
Expand All @@ -56,12 +94,30 @@ const WalletQRCodeExportModal = ({ onClose }: { onClose: () => void }) => {
</div>
) : (
<Section>
<InfoBox text={t('Scan this QR code with your mobile wallet.')} Icon={ScanLine} importance="accent" />
<QRCode size={550} value={qrCodeTextToEncode} bgColor={theme.bg.primary} fgColor={theme.font.primary} />
<InfoBox
text={t('Scan this animated QR code with your mobile wallet.')}
Icon={ScanLine}
importance="accent"
/>
<QRCodeLoop>
{frames.map((data, i) => (
<div key={i} style={{ position: 'absolute', opacity: i === frame ? 1 : 0 }}>
<QRCode size={460} value={data} bgColor={theme.bg.primary} fgColor={theme.font.primary} />
</div>
))}
</QRCodeLoop>
</Section>
)}
</CenteredModal>
)
}

export default WalletQRCodeExportModal

const QRCodeLoop = styled.div`
position: relative;
height: 460px;
width: 100%;
display: flex;
justify-content: center;
`

0 comments on commit 3a4138f

Please sign in to comment.