bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
70 lines (69 loc) • 5.05 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { CheckCircledIcon, DownloadIcon } from "@radix-ui/react-icons";
import { useState } from "react";
import { cn } from "../../lib/utils.js";
import { Button } from "../ui/button.js";
import { Card, CardContent } from "../ui/card.js";
export function BackupDownload({ backup, password, onDownloaded, requireDownload = false, className = "", }) {
const [downloaded, setDownloaded] = useState(false);
const [isDownloading, setIsDownloading] = useState(false);
const handleDownload = async () => {
setIsDownloading(true);
try {
let dataToDownload;
let filename;
if (password) {
// Encrypt the backup if password is provided
const { encryptBackup } = await import("bitcoin-backup");
const encrypted = await encryptBackup(backup, password);
// encryptBackup returns a Base64 string, don't double-stringify it
dataToDownload = encrypted;
filename = `bitcoin-auth-backup-${Date.now()}.txt`;
}
else {
// Download unencrypted backup - determine extension based on backup type
const backupData = JSON.stringify(backup, null, 2);
dataToDownload = backupData;
// Check backup type for appropriate extension
if ("wif" in backup && !("xprv" in backup) && !("mnemonic" in backup)) {
// WifBackup - simple WIF backup
filename = `bitcoin-auth-backup-${Date.now()}.txt`;
}
else {
// BapMasterBackup, BapMemberBackup, OneSatBackup - JSON format
filename = `bitcoin-auth-backup-${Date.now()}.json`;
}
}
// Create blob and download
const blob = new Blob([dataToDownload], {
type: password
? "text/plain"
: filename.endsWith(".txt")
? "text/plain"
: "application/json",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
setDownloaded(true);
onDownloaded?.();
}
catch (error) {
console.error("Download error:", error);
}
finally {
setIsDownloading(false);
}
};
return (_jsx(Card, { className: cn("w-full", className), children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(DownloadIcon, { className: "h-5 w-5 text-primary", "aria-label": "Download" }), _jsx("p", { className: "font-medium text-base", children: password ? "Encrypted Backup" : "Master Backup" })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: password
? "Download your encrypted backup file. You'll need your password to restore it."
: "Download your complete identity backup. Keep this file secure." }), _jsx(Button, { size: "lg", variant: downloaded ? "secondary" : "default", onClick: handleDownload, disabled: isDownloading, className: cn("w-full", downloaded && "bg-green-50 hover:bg-green-100 text-green-700"), children: isDownloading ? (_jsxs(_Fragment, { children: [_jsxs("svg", { className: "animate-spin h-4 w-4 mr-2", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", role: "img", "aria-label": "Loading", children: [_jsx("title", { children: "Loading" }), _jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "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" })] }), "Preparing..."] })) : (_jsxs(_Fragment, { children: [downloaded ? (_jsx(CheckCircledIcon, { className: "h-4 w-4 mr-2", "aria-label": "Success" })) : (_jsx(DownloadIcon, { className: "h-4 w-4 mr-2", "aria-label": "Download" })), downloaded
? "Downloaded"
: `Download ${password ? "Encrypted" : "Master"} Backup`] })) }), downloaded && (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(CheckCircledIcon, { className: "h-4 w-4 text-green-600" }), _jsx("p", { className: "text-xs text-green-600", children: "Backup saved to your downloads folder" })] })), requireDownload && !downloaded && (_jsx("p", { className: "text-xs text-amber-600", children: "You must download your backup before continuing" }))] }) }) }));
}