feat(debug): add /debug page with NIP-46 encrypt→decrypt probes for nip04/nip44

This commit is contained in:
Gigi
2025-10-17 10:37:45 +02:00
parent fbffa03dad
commit ea6220277d
2 changed files with 61 additions and 0 deletions

View File

@@ -17,6 +17,7 @@ import { useToast } from './hooks/useToast'
import { useOnlineStatus } from './hooks/useOnlineStatus'
import { RELAYS } from './config/relays'
import { SkeletonThemeProvider } from './components/Skeletons'
import Debug from './components/Debug'
const DEFAULT_ARTICLE = import.meta.env.VITE_DEFAULT_ARTICLE_NADDR ||
'naddr1qvzqqqr4gupzqmjxss3dld622uu8q25gywum9qtg4w4cv4064jmg20xsac2aam5nqqxnzd3cxqmrzv3exgmr2wfesgsmew'
@@ -168,6 +169,7 @@ function AppRoutes({
/>
}
/>
<Route path="/debug" element={<Debug />} />
<Route path="/" element={<Navigate to={`/a/${DEFAULT_ARTICLE}`} replace />} />
</Routes>
)

59
src/components/Debug.tsx Normal file
View File

@@ -0,0 +1,59 @@
import React, { useMemo, useState } from 'react'
import { Hooks } from 'applesauce-react'
const Debug: React.FC = () => {
const activeAccount = Hooks.useActiveAccount()
const [result, setResult] = useState<string>('')
const [error, setError] = useState<string>('')
const signer = useMemo(() => (activeAccount as unknown as { signer?: unknown })?.signer, [activeAccount])
const hasNip04 = typeof (signer as { nip04?: { encrypt?: unknown; decrypt?: unknown } } | undefined)?.nip04?.encrypt === 'function'
const hasNip44 = typeof (signer as { nip44?: { encrypt?: unknown; decrypt?: unknown } } | undefined)?.nip44?.encrypt === 'function'
const pubkey = (activeAccount as unknown as { pubkey?: string })?.pubkey
const doRoundtrip = async (mode: 'nip04' | 'nip44') => {
setResult('')
setError('')
if (!signer || !pubkey) {
setError('No active signer/pubkey')
return
}
try {
const api = (signer as any)[mode]
if (!api || typeof api.encrypt !== 'function' || typeof api.decrypt !== 'function') {
setError(`${mode} not available on signer`)
return
}
const cipher = await api.encrypt(pubkey, `debug-${mode}-${Date.now()}`)
const plain = await api.decrypt(pubkey, cipher)
setResult(String(plain))
} catch (e) {
setError(e instanceof Error ? e.message : String(e))
}
}
return (
<div className="content-panel">
<h2>Debug / NIP-46 Echo</h2>
<div className="card">
<div className="card-body">
<div>Active pubkey: <code>{pubkey || 'none'}</code></div>
<div>Signer has nip04: <strong>{hasNip04 ? 'yes' : 'no'}</strong></div>
<div>Signer has nip44: <strong>{hasNip44 ? 'yes' : 'no'}</strong></div>
<div className="flex gap-2 mt-3">
<button className="btn btn-primary" onClick={() => doRoundtrip('nip44')} disabled={!hasNip44}>Probe nip44 encryptdecrypt</button>
<button className="btn" onClick={() => doRoundtrip('nip04')} disabled={!hasNip04}>Probe nip04 encryptdecrypt</button>
</div>
{result && (
<div className="alert alert-success mt-3">Plaintext: <code>{result}</code></div>
)}
{error && (
<div className="alert alert-error mt-3">Error: {error}</div>
)}
</div>
</div>
</div>
)
}
export default Debug