Use Inscriboor for page signing

This commit is contained in:
matcha committed 2026-10-05 04:54:54 +00:00
1 parent f12e8023c7
commit 2333dad0dc
1 file changed
+30 -7
+30 -7
View File
@@ -4,7 +4,8 @@ import { encodeMetadata, parseMetadataJSON } from './adapters/metadata.js';
import { MetadataIndex, deriveProtocol } from './adapters/metadata-index.js';
import { LocalOrdAPI } from './adapters/local-ord-api.js';
import { mineLab, setMiner, minerStatus } from './miner.js';
import { TestWallet } from './adapters/wallet.js';
import { TestWallet, ExtensionWallet, loadWalletBackup } from './adapters/wallet.js';
import { inscribeWithProvider } from './adapters/extension-inscription.js';
import { LocalRPC } from './adapters/chain.js';
import { InscriptionAdapter, MAX_BYTES, MIME_TYPES } from './adapters/inscription.js';
import { preview, clearPreviews } from './preview.js';
@@ -16,6 +17,7 @@ const short = id => `${id.slice(0, 12)}…${id.slice(-8)}`;
const THEME_KEY = 'super-testnet-theme';
let fileBytes = null, fileLoading = false, fileRevision = 0;
let lab, busy = false, reviewed = null, failed = false;
let inscriboorProvider = null;
const message = (text, error = false) => { $('status').textContent = text; $('status').classList.toggle('error', error); };
const el = (tag, text, className) => { const node = document.createElement(tag); if (text !== undefined) node.textContent = text; if (className) node.className = className; return node; };
@@ -166,8 +168,9 @@ function render() {
const wallet = lab?.wallet, chain = lab?.chain;
const disabled = busy || failed;
$('empty-wallet').hidden = !!wallet; $('active-wallet').hidden = !wallet;
$('wallet-state').textContent = wallet ? 'LOCAL / TEST ONLY' : 'NOT CREATED';
$('create-wallet').disabled = disabled; $('load-wallet').disabled = disabled;
$('wallet-state').textContent = wallet ? (wallet.kind === 'extension-wallet' ? 'INSCRIBOOR / TEST' : 'LOCAL / TEST ONLY') : 'NOT CREATED';
$('create-wallet').disabled = disabled; $('connect-inscriboor').disabled = disabled || !inscriboorProvider; $('load-wallet').disabled = disabled;
$('inscriboor-status').textContent = inscriboorProvider ? 'Inscriboor detected - extension key stays outside this page.' : 'Inscriboor not detected. Reload the extension or use the local test wallet.';
$('mine').disabled = disabled || !wallet;
$('miner-interval').disabled = disabled || !wallet;
$('miner-interval').value = String(lab?.miner?.interval ?? 0);
@@ -184,6 +187,8 @@ function render() {
$('balance').textContent = btc(chain.balance(wallet.script));
const reserved = chain.coins(wallet.script).filter(c => c.inscription).reduce((n,c) => n+c.value,0);
$('reserved').textContent = `${reserved.toLocaleString()} sats protected in collectibles · balance includes pending outputs`;
$('export-wallet').textContent = wallet.kind === 'extension-wallet' ? 'Save wallet descriptor' : 'Save test wallet';
$('signing-note').textContent = wallet.kind === 'extension-wallet' ? 'The next button opens Inscriboor for approval. The page never receives the extension key.' : 'The next button signs locally with this browser test wallet and submits commit + reveal.';
}
const items = wallet ? new InscriptionAdapter(chain, wallet).list() : [];
const selectedParent = $('parent').value;
@@ -232,6 +237,17 @@ $('create-wallet').onclick = () => mutate(next => {
if (next.wallet) throw new Error('A wallet already exists in this browser. Reload to use it.');
next.wallet = TestWallet.create();
}, 'Test wallet created. Next: mine a block to get 50 fake BTC.');
$('connect-inscriboor').onclick = async () => {
try {
const provider = inscriboorProvider ?? window.inscriboor;
if (!provider?.request) throw new Error('Inscriboor extension not detected.');
const account = (await provider.request({ method:'bitcoin_getAccounts' }))?.[0];
await mutate(next => {
if (next.wallet) throw new Error('A wallet already exists in this browser. Reset or restore a different lab first.');
next.wallet = new ExtensionWallet(account, provider);
}, 'Inscriboor connected. Mine a block, prepare an inscription, then approve it in the extension.');
} catch (error) { message(error.message, true); }
};
const mine = automatic => mutate(next => mineLab(next, automatic), 'Block mined. Pending transactions moved from the mempool into your newest block.');
$('mine').onclick = () => mine(false);
$('miner-interval').onchange = () => {
@@ -289,9 +305,14 @@ $('cancel-review').onclick = closeReview;
$('sign').onclick = () => {
const consent = reviewed;
if (!consent) return;
mutate(next => {
mutate(async next => {
if (next.wallet?.address !== consent.address) throw new Error('Wallet changed. Review again before signing.');
new InscriptionAdapter(next.chain, next.wallet).inscribe(consent.payload, consent.parent, consent.metadata, consent.options);
if (next.wallet.kind === 'extension-wallet') {
const provider = inscriboorProvider ?? window.inscriboor;
if (!provider?.request) throw new Error('Reconnect the Inscriboor extension before signing.');
next.wallet.attach(provider);
await inscribeWithProvider(next.chain, next.wallet, consent.payload, consent.parent, consent.metadata, consent.options);
} else new InscriptionAdapter(next.chain, next.wallet).inscribe(consent.payload, consent.parent, consent.metadata, consent.options);
}, 'Inscription submitted. Its commit + reveal are now visible in the mempool; mine a block to confirm them.', resetComposer);
};
$('export-wallet').onclick = () => download('super-testnet-wallet.json', JSON.stringify(lab.wallet.backup(), null, 2));
@@ -306,7 +327,7 @@ $('load-wallet').onchange = async event => {
try {
const raw = await file.text(), data = JSON.parse(raw);
const restore = data.kind === 'test-lab';
const loaded = restore ? decodeLab(raw) : TestWallet.load(data);
const loaded = restore ? decodeLab(raw) : loadWalletBackup(data);
if (lab.wallet && !confirm(restore ? 'Replace this entire local lab with the backup? Save your current lab first.' : 'Switch the active test wallet? The local chain stays here. Save your current wallet first.')) return;
await mutate(next => {
if (restore) Object.assign(next, loaded); else next.wallet = loaded;
@@ -382,9 +403,11 @@ window.addEventListener('storage', event => {
closeReview(); load(); if (!failed) message('Local lab changed in another tab; refreshed.');
});
function load() {
try { lab = readLab(); failed = false; if (lab.wallet) message('Test wallet loaded from this browser. Your local chain is ready.'); }
try { lab = readLab(); failed = false; if (lab.wallet?.kind === 'extension-wallet' && inscriboorProvider) lab.wallet.attach(inscriboorProvider); if (lab.wallet) message(lab.wallet.kind === 'extension-wallet' ? 'Inscriboor wallet descriptor loaded. Reconnect the extension to sign.' : 'Test wallet loaded from this browser. Your local chain is ready.'); }
catch (error) { failed = true; message(`Cannot load saved lab: ${error.message} Export it for recovery, then reset this local lab.`, true); }
render();
}
window.addEventListener('inscriboor#initialized', () => { inscriboorProvider = window.inscriboor; if (lab?.wallet?.kind === 'extension-wallet') lab.wallet.attach(inscriboorProvider); render(); });
inscriboorProvider = window.inscriboor?.isInscriboor ? window.inscriboor : null;
initTheme();
load();