// Keeps Wallet - Beacon Confirmation Popup
// Reads pending request from background, shows details, sends approval/rejection
(async function () {
'use strict';
const contentEl = document.getElementById('content');
// Get requestId from URL params
const params = new URLSearchParams(window.location.search);
const requestId = params.get('requestId');
if (!requestId) {
contentEl.innerHTML = '
No request ID provided.
';
return;
}
// Fetch pending request details from background
let pending;
try {
pending = await chrome.runtime.sendMessage({
type: 'BEACON_GET_PENDING',
payload: { requestId },
});
} catch (err) {
contentEl.innerHTML =
'Failed to load request details.
';
return;
}
if (pending.error) {
contentEl.innerHTML = `${escapeHtml(pending.error)}
`;
return;
}
// Render based on request type
const { requestType, peerName, peerIcon, request, walletAddress } = pending;
let detailsHtml = '';
switch (requestType) {
case 'permission_request':
detailsHtml = renderPermissionRequest(request, walletAddress);
break;
case 'operation_request':
detailsHtml = renderOperationRequest(request, walletAddress);
break;
case 'sign_payload_request':
detailsHtml = renderSignPayloadRequest(request, walletAddress);
break;
default:
detailsHtml = `
Type
${escapeHtml(requestType)}
`;
}
const requestLabel = formatRequestType(requestType);
contentEl.innerHTML = `
${escapeHtml(peerName)}
${escapeHtml(requestLabel)}
${detailsHtml}
`;
// Button handlers
document.getElementById('btn-approve').addEventListener('click', async () => {
await sendConfirmation(true);
});
document.getElementById('btn-reject').addEventListener('click', async () => {
await sendConfirmation(false);
});
// Close window on Escape
document.addEventListener('keydown', async (e) => {
if (e.key === 'Escape') {
await sendConfirmation(false);
}
});
async function sendConfirmation(approved) {
// Disable buttons to prevent double-click
const approveBtn = document.getElementById('btn-approve');
const rejectBtn = document.getElementById('btn-reject');
if (approveBtn) approveBtn.disabled = true;
if (rejectBtn) rejectBtn.disabled = true;
try {
await chrome.runtime.sendMessage({
type: 'BEACON_CONFIRM',
payload: { requestId, approved },
});
} catch (err) {
console.error('Failed to send confirmation:', err);
}
// Close the popup window
window.close();
}
// --- Render helpers ---
function renderPermissionRequest(req, address) {
const network = req.network?.type || 'unknown';
const scopes = req.scopes
? req.scopes.join(', ')
: 'sign, operation_request';
return `
Wants to connect
This dApp is requesting permission to see your address and request signatures.
Your Address
${escapeHtml(address || 'Unknown')}
Network
${escapeHtml(network)}
Scopes
${escapeHtml(scopes)}
`;
}
function renderOperationRequest(req, address) {
const ops = req.operationDetails || [];
let opsHtml = '';
for (const op of ops) {
let detail = '';
if (op.kind === 'transaction') {
const amount = op.amount
? (parseInt(op.amount) / 1000000).toFixed(6) + ' tez'
: '0 tez';
detail = `To: ${escapeHtml(op.destination || '?')} | ${amount}`;
if (op.parameters) {
detail += ` | Entrypoint: ${escapeHtml(op.parameters.entrypoint || '?')}`;
}
} else if (op.kind === 'delegation') {
detail = op.delegate
? `Delegate to: ${escapeHtml(op.delegate)}`
: 'Remove delegation';
} else if (op.kind === 'origination') {
detail = 'Deploy new contract';
}
opsHtml += `
${escapeHtml(op.kind)}
${detail ? `
${detail}
` : ''}
`;
}
return `
From
${escapeHtml(address || 'Unknown')}
Operations (${ops.length})
${opsHtml || '
No operations
'}
`;
}
function renderSignPayloadRequest(req, address) {
const payload = req.payload || '';
// Truncate long payloads for display
const displayPayload =
payload.length > 200 ? payload.substring(0, 200) + '...' : payload;
const signingType = req.signingType || 'raw';
return `
Signing Type
${escapeHtml(signingType)}
Payload
${escapeHtml(displayPayload)}
Signing As
${escapeHtml(address || 'Unknown')}
`;
}
function formatRequestType(type) {
switch (type) {
case 'permission_request':
return 'Connect';
case 'operation_request':
return 'Sign Operation';
case 'sign_payload_request':
return 'Sign Payload';
default:
return type;
}
}
function escapeHtml(str) {
if (!str) return '';
return String(str)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
})();