bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
167 lines (166 loc) • 6.68 kB
JavaScript
import { ECIES, PublicKey, Utils } from "@bsv/sdk";
// useBapEncryption Hook - Encrypt/decrypt with BAP identity using React Query pattern
import { useMutation } from "@tanstack/react-query";
import { useBitcoinAuth } from "../../../hooks/useBitcoinAuth.js";
const { electrumEncrypt, electrumDecrypt } = ECIES;
const { toArray, toBase64, toUTF8 } = Utils;
export function useBapEncryption(options = {}) {
const { useType42: _useType42 = false } = options;
const { user } = useBitcoinAuth();
// Get BAP instance from context
const bapInstance = user?.bapInstance;
// Encryption mutation
const encryptMutation = useMutation({
mutationFn: async ({ content, options: encryptOptions = {} }) => {
if (!bapInstance) {
throw new Error("BAP instance not available");
}
try {
const ids = bapInstance.listIds();
if (!ids || ids.length === 0) {
throw new Error("No BAP identity available");
}
const currentId = ids[0];
if (!currentId) {
throw new Error("Invalid BAP identity");
}
const identity = bapInstance.getId(currentId.idKey);
if (!identity) {
throw new Error("BAP identity not found");
}
// Get encryption key from the identity
const encryptionKey = encryptOptions.useType42
? identity.getEncryptionKeyType42()
: identity.getEncryptionKey();
// Get recipient public key or use self
let targetPubKey;
if (encryptOptions.recipientPublicKey) {
targetPubKey = PublicKey.fromString(encryptOptions.recipientPublicKey);
}
else {
targetPubKey = encryptionKey.pubKey;
}
// Perform ECIES encryption
const encrypted = toBase64(electrumEncrypt(toArray(content, "utf8"), targetPubKey, encryptOptions.recipientPublicKey
? encryptionKey.privKey
: undefined));
const encryptedData = {
encrypted,
type: encryptOptions.type || "message",
mode: encryptOptions.mode || "asymmetric",
recipientPublicKey: encryptOptions.recipientPublicKey,
timestamp: new Date(),
metadata: encryptOptions.metadata,
};
return {
success: true,
data: encryptedData,
};
}
catch (error) {
return {
success: false,
error: error,
};
}
},
});
// Decryption mutation
const decryptMutation = useMutation({
mutationFn: async ({ encryptedContent, options: decryptOptions = {} }) => {
if (!bapInstance) {
throw new Error("BAP instance not available");
}
try {
const ids = bapInstance.listIds();
if (!ids || ids.length === 0) {
throw new Error("No BAP identity available");
}
const currentId = ids[0];
if (!currentId) {
throw new Error("Invalid BAP identity");
}
const identity = bapInstance.getId(currentId.idKey);
if (!identity) {
throw new Error("BAP identity not found");
}
// Get encryption key from the identity
const encryptionKey = decryptOptions.useType42
? identity.getEncryptionKeyType42()
: identity.getEncryptionKey();
// Get sender public key if provided
let senderPubKey;
if (decryptOptions.senderPublicKey) {
senderPubKey = PublicKey.fromString(decryptOptions.senderPublicKey);
}
// Perform ECIES decryption
const decryptedBytes = electrumDecrypt(toArray(encryptedContent, "base64"), encryptionKey.privKey, senderPubKey);
const content = toUTF8(decryptedBytes);
const decryptedData = {
content,
type: decryptOptions.type || "message",
decryptedAt: new Date(),
senderAddress: "mock-address",
};
return {
success: true,
data: decryptedData,
};
}
catch (error) {
return {
success: false,
error: error,
};
}
},
});
// Get encryption key info
const getEncryptionKey = () => {
if (!bapInstance)
return null;
try {
const ids = bapInstance.listIds();
if (!ids || ids.length === 0)
return null;
const currentId = ids[0];
if (!currentId)
return null;
const identity = bapInstance.getId(currentId.idKey);
if (!identity)
return null;
// Get the actual encryption key from the identity
const encryptionKey = options.useType42
? identity.getEncryptionKeyType42()
: identity.getEncryptionKey();
return {
publicKey: encryptionKey.pubKey.toString(),
address: identity.getCurrentAddress(),
identityKey: currentId.idKey,
};
}
catch {
return null;
}
};
return {
// React Query mutation interface
encrypt: encryptMutation.mutate,
encryptAsync: encryptMutation.mutateAsync,
decrypt: decryptMutation.mutate,
decryptAsync: decryptMutation.mutateAsync,
// State
isLoading: encryptMutation.isPending || decryptMutation.isPending,
isError: encryptMutation.isError || decryptMutation.isError,
isSuccess: encryptMutation.isSuccess || decryptMutation.isSuccess,
error: encryptMutation.error || decryptMutation.error,
data: encryptMutation.data || decryptMutation.data,
// Helpers
getEncryptionKey,
// Reset
reset: () => {
encryptMutation.reset();
decryptMutation.reset();
},
};
}