UNPKG

bigblocks

Version:

Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React

17 lines 6.41 kB
{ "name": "backup-recovery-backupdownload", "type": "registry:component", "dependencies": [ "@radix-ui/react-icons" ], "devDependencies": [], "registryDependencies": [], "files": [ { "path": "components/backup-recovery/BackupDownload.tsx", "type": "registry:component", "content": "\"use client\";\n\nimport { CheckCircledIcon, DownloadIcon } from \"@radix-ui/react-icons\";\nimport { useState } from \"react\";\nimport type { BapMasterBackup } from \"../../lib/types.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Card, CardContent } from \"../ui/card.js\";\n\nexport interface BackupDownloadProps {\n\tbackup: BapMasterBackup;\n\tpassword?: string;\n\tonDownloaded?: () => void;\n\trequireDownload?: boolean;\n\tclassName?: string;\n}\n\nexport function BackupDownload({\n\tbackup,\n\tpassword,\n\tonDownloaded,\n\trequireDownload = false,\n\tclassName = \"\",\n}: BackupDownloadProps) {\n\tconst [downloaded, setDownloaded] = useState(false);\n\tconst [isDownloading, setIsDownloading] = useState(false);\n\n\tconst handleDownload = async () => {\n\t\tsetIsDownloading(true);\n\n\t\ttry {\n\t\t\tlet dataToDownload: string;\n\t\t\tlet filename: string;\n\n\t\t\tif (password) {\n\t\t\t\t// Encrypt the backup if password is provided\n\t\t\t\tconst { encryptBackup } = await import(\"bitcoin-backup\");\n\t\t\t\tconst encrypted = await encryptBackup(backup, password);\n\t\t\t\t// encryptBackup returns a Base64 string, don't double-stringify it\n\t\t\t\tdataToDownload = encrypted;\n\t\t\t\tfilename = `bitcoin-auth-backup-${Date.now()}.txt`;\n\t\t\t} else {\n\t\t\t\t// Download unencrypted backup - determine extension based on backup type\n\t\t\t\tconst backupData = JSON.stringify(backup, null, 2);\n\t\t\t\tdataToDownload = backupData;\n\n\t\t\t\t// Check backup type for appropriate extension\n\t\t\t\tif (\"wif\" in backup && !(\"xprv\" in backup) && !(\"mnemonic\" in backup)) {\n\t\t\t\t\t// WifBackup - simple WIF backup\n\t\t\t\t\tfilename = `bitcoin-auth-backup-${Date.now()}.txt`;\n\t\t\t\t} else {\n\t\t\t\t\t// BapMasterBackup, BapMemberBackup, OneSatBackup - JSON format\n\t\t\t\t\tfilename = `bitcoin-auth-backup-${Date.now()}.json`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create blob and download\n\t\t\tconst blob = new Blob([dataToDownload], {\n\t\t\t\ttype: password\n\t\t\t\t\t? \"text/plain\"\n\t\t\t\t\t: filename.endsWith(\".txt\")\n\t\t\t\t\t\t? \"text/plain\"\n\t\t\t\t\t\t: \"application/json\",\n\t\t\t});\n\t\t\tconst url = URL.createObjectURL(blob);\n\t\t\tconst a = document.createElement(\"a\");\n\t\t\ta.href = url;\n\t\t\ta.download = filename;\n\t\t\tdocument.body.appendChild(a);\n\t\t\ta.click();\n\t\t\tdocument.body.removeChild(a);\n\t\t\tURL.revokeObjectURL(url);\n\n\t\t\tsetDownloaded(true);\n\t\t\tonDownloaded?.();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Download error:\", error);\n\t\t} finally {\n\t\t\tsetIsDownloading(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<Card className={cn(\"w-full\", className)}>\n\t\t\t<CardContent className=\"pt-6\">\n\t\t\t\t<div className=\"space-y-3\">\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<DownloadIcon\n\t\t\t\t\t\t\tclassName=\"h-5 w-5 text-primary\"\n\t\t\t\t\t\t\taria-label=\"Download\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<p className=\"font-medium text-base\">\n\t\t\t\t\t\t\t{password ? \"Encrypted Backup\" : \"Master Backup\"}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{password\n\t\t\t\t\t\t\t? \"Download your encrypted backup file. You'll need your password to restore it.\"\n\t\t\t\t\t\t\t: \"Download your complete identity backup. Keep this file secure.\"}\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<Button\n\t\t\t\t\t\tsize=\"lg\"\n\t\t\t\t\t\tvariant={downloaded ? \"secondary\" : \"default\"}\n\t\t\t\t\t\tonClick={handleDownload}\n\t\t\t\t\t\tdisabled={isDownloading}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"w-full\",\n\t\t\t\t\t\t\tdownloaded && \"bg-green-50 hover:bg-green-100 text-green-700\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isDownloading ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\tclassName=\"animate-spin h-4 w-4 mr-2\"\n\t\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\trole=\"img\"\n\t\t\t\t\t\t\t\t\taria-label=\"Loading\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<title>Loading</title>\n\t\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\t\tclassName=\"opacity-25\"\n\t\t\t\t\t\t\t\t\t\tcx=\"12\"\n\t\t\t\t\t\t\t\t\t\tcy=\"12\"\n\t\t\t\t\t\t\t\t\t\tr=\"10\"\n\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\tstrokeWidth=\"4\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\tclassName=\"opacity-75\"\n\t\t\t\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\td=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\tPreparing...\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{downloaded ? (\n\t\t\t\t\t\t\t\t\t<CheckCircledIcon\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-4 w-4 mr-2\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Success\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<DownloadIcon\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-4 w-4 mr-2\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Download\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{downloaded\n\t\t\t\t\t\t\t\t\t? \"Downloaded\"\n\t\t\t\t\t\t\t\t\t: `Download ${password ? \"Encrypted\" : \"Master\"} Backup`}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Button>\n\n\t\t\t\t\t{downloaded && (\n\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t<CheckCircledIcon className=\"h-4 w-4 text-green-600\" />\n\t\t\t\t\t\t\t<p className=\"text-xs text-green-600\">\n\t\t\t\t\t\t\t\tBackup saved to your downloads folder\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{requireDownload && !downloaded && (\n\t\t\t\t\t\t<p className=\"text-xs text-amber-600\">\n\t\t\t\t\t\t\tYou must download your backup before continuing\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n", "target": "<%- config.aliases.components %>/backupdownload.tsx" } ] }