Preserve hosted website UX inside Archipelago, add isolated Business and owner-authorized native wallet setup, and include deployment handoff. Based on main with native signer import already accepted.
73 lines
3.6 KiB
JavaScript
73 lines
3.6 KiB
JavaScript
import { link, base } from './ds/frame.js';
|
||
import { prod } from './ds/env.js';
|
||
import { moduleQrUrl } from './module-qr.js?v=2';
|
||
|
||
// The dashboard and the printable master use one destination catalog.
|
||
export const freeDefinitions = [
|
||
['justworks', 'Just Works page', 'Your public merchant page', 'JW'],
|
||
['tip', 'Tip', 'Bitcoin tips and community wall', '⚡'],
|
||
['nsite', 'nsite', 'Your site on Nostr', 'NS'],
|
||
['nostr', 'Nostr profile', 'Your signed identity', 'NP'],
|
||
['maps', 'Maps', 'Find your place on the map', '⌖'],
|
||
['gallery', 'Gallery', 'Photos and discovery', '□'],
|
||
];
|
||
export const businessDefinitions = [
|
||
['pos', 'POS', 'Run orders and payments', 'Counter view', '↗', false],
|
||
['order', 'Order', 'Order to table', 'Customer', '+', true],
|
||
['pay', 'Pay Bill', 'Settle an open order', 'Customer', '€', true],
|
||
['payandgo', 'Just Pay', 'Pay a paper receipt', 'Customer', '₿', true],
|
||
['booking', 'Bookings', 'Tables now or later', 'Customer', '⌁', true, 'book'],
|
||
['screen', 'Screen', 'Merchant media display', '4K display', '▣', true],
|
||
['stats', 'Stats', 'Audience, actions and revenue', 'Merchant view', '↗', true, 'business'],
|
||
['events', 'Events', 'Merchant Nostr events', 'Coming soon', '◌', true],
|
||
];
|
||
|
||
export function businessUrl(npub, sheet = false) {
|
||
const path = sheet ? '/qr-sheet' : prod ? '/' : '/dashboard';
|
||
return `${prod ? 'https://business.justworks.cash' : location.origin + base}${path}?npub=${encodeURIComponent(npub)}`;
|
||
}
|
||
|
||
export function moduleDestination(definition, data, npub) {
|
||
const [id, , , , , configurable, target = id] = definition;
|
||
const state = data.modules?.[id] || {};
|
||
const paymentSetup = ['pay', 'payandgo'].includes(id) && !data.payment_ready;
|
||
const disabled = id === 'events' || state.status === 'coming-soon' || paymentSetup;
|
||
const url = paymentSetup
|
||
? `${base}/profile?npub=${encodeURIComponent(npub)}#lightning`
|
||
: id === 'stats'
|
||
? `${prod ? 'https://business.justworks.cash' : base}/stats?npub=${encodeURIComponent(npub)}`
|
||
: prod ? `https://${target}.justworks.cash/?npub=${encodeURIComponent(npub)}` : link(target);
|
||
return {state, paymentSetup, disabled, url,
|
||
qrUrl: disabled ? '' : moduleQrUrl(url, npub),
|
||
available: !disabled && (!configurable || !!state.enabled)};
|
||
}
|
||
|
||
export function sheetDestinations(data, npub) {
|
||
return [
|
||
{id: 'business', title: 'Business dashboard', url: businessUrl(npub)},
|
||
...freeDefinitions.filter(([id]) => data.links?.[id] && data.links[id] !== '#')
|
||
.map(([id, title]) => ({id, title, url: data.links[id]})),
|
||
...businessDefinitions.flatMap(definition => {
|
||
const destination = moduleDestination(definition, data, npub);
|
||
return destination.available ? [{id: definition[0], title: definition[1], url: destination.qrUrl}] : [];
|
||
}),
|
||
];
|
||
}
|
||
|
||
// Verify the Bech32 checksum and the 32-byte public-key payload, without a CDN.
|
||
export function validNpub(value) {
|
||
if (!/^npub1[023456789acdefghjklmnpqrstuvwxyz]{58}$/.test(value || '')) return false;
|
||
const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
||
const words = [...value.slice(5)].map(char => alphabet.indexOf(char));
|
||
let checksum = 1;
|
||
const expanded = [...'npub'].map(char => char.charCodeAt(0) >> 5)
|
||
.concat(0, [...'npub'].map(char => char.charCodeAt(0) & 31), words);
|
||
const generators = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
||
for (const word of expanded) {
|
||
const top = checksum >>> 25;
|
||
checksum = ((checksum & 0x1ffffff) << 5) ^ word;
|
||
for (let bit = 0; bit < 5; bit++) if ((top >>> bit) & 1) checksum ^= generators[bit];
|
||
}
|
||
return checksum === 1 && (words[51] & 15) === 0;
|
||
}
|