Chapter 12 · Synthesis
Validate, build a details object, wrap, sign, encode. If you can say that sentence with the right details class and flags, you can add a tab.
FIGURE 12.1 · The whole app in one grid.
Every tab does the same four things: validate input, build a details object, wrap it in a
GenericRequest, sign and encode. What differs is only which details object and
which flags — and, in two cases, that more than one detail is needed.
// routes/requests/myThing.ts
import { MyThingRequestDetails, MyThingRequestOrdinalVDXFObject } from "verus-typescript-primitives";
import { buildGenericRequestFromDetails, signRequest, getRpcConfig,
requireString, parseRedirectsField } from "../utils";
export async function generateMyThingQr(req, res) {
try {
const signingId = requireString(req.body.signingId, "signingId");
const redirects = parseRedirectsField(req.body.redirects);
const { rpcHost, rpcPort, rpcUser, rpcPassword, isTestnet } = getRpcConfig();
const details = new MyThingRequestDetails({ /* form fields */ });
const request = buildGenericRequestFromDetails({
details: [new MyThingRequestOrdinalVDXFObject({ data: details })],
signed: true, signingId, redirects
}, isTestnet);
await signRequest({ request, rpcHost, rpcPort, rpcUser, rpcPassword, signingId });
const deeplink = request.toWalletDeeplinkUri();
res.json({ deeplink, qrDataUrl: await QRCode.toDataURL(deeplink) });
} catch (e) {
res.status(e.name === "ValidationError" ? 400 : 500).json({ error: e.message });
}
}
Then mount it in server.ts and add a form view. That is genuinely the whole recipe; the
rest of each route file is validation and the odd workaround.
getRawDataSha256(false) before
signatureAsVch is set, every time.the primitives book → for the byte-level meaning of each details class src/routes/utils.ts → the shared pipeline, read end to end __tests__/ → concrete expected outputs per tab docs/ → per-tab manual test notes and design plans