Chapter 04 · Tabs
The only tab with a server-side lifecycle: a generated request id, an automatic callback, a status endpoint, and a service identity holding the key.
FIGURE 4.1 · Who does what in the service-signer flow.
Every other tab signs with a user identity that lives in the daemon's wallet. The service-signer tab
signs with a service identity configured on the server
(SERVICE_SIGNER_IADDRESS / SERVICE_SIGNER_WIF), targets someone else's
identity, and uses the QR only to get the user's authorisation.
That is the model used by provisioning and conversion services: the user authorises by scanning, the
service performs the update. The request is still a normal
IdentityUpdateRequestOrdinalVDXFObject — what differs is who signed it and how the answer
comes back.
1. requestId = generateRequestId() // new i-address-ish id per request
2. redirects = ensureCallbackRedirect(redirects, uri) // adds type "1" -> /api/service-signer/callback
3. { name, parent } = getidentity(targetIdentity) // RPC, must resolve
4. merged = { ...identityChanges, name, parent, contentmultimap }
5. details = IdentityUpdateRequestDetails.fromCLIJson(merged, { requestid })
6. request = buildGenericRequestFromDetails({ details, signed: true,
signingId: SERVICE_SIGNER_IADDRESS, redirects })
7. signRequest(...) with the service signing id
8. QR / deeplink
Note step 3: the tab refuses to build a request if the target identity's name and parent cannot be resolved. A partial identity that names an identity by something the chain cannot resolve is a request the wallet would reject anyway.
| Endpoint | Purpose |
|---|---|
GET /api/service-signer/callback?requestId=… | Wallet redirect target; renders a page that then polls status |
POST /api/service-signer/callback?requestId=… | Programmatic callback carrying the wallet's response |
GET /api/service-signer/status?requestId=… | Poll request state (pending / complete / error) |
parseIdentityUpdateResponse extracts the txid from the wallet's response and
stores it against the request id. The UI polls status until it sees one. This is the only tab with a
server-side lifecycle — everything else is request/response in a single HTTP call.
buildResponseUris drops unknown types silently, the failure looks like a wallet
problem rather than a form problem.
A 22-line CLI helper: given a VDXF key URI, it constructs a DefinedKey, prints its
i-address, and emits the identity-update JSON fragment that registers it under
DATA_TYPE_DEFINEDKEY. It is how you create the key you will then write into a content
multimap in the update tab.
src/routes/requests/serviceSigner.ts ├── generateServiceSignerQr # assembly + QR ├── serviceSignerCallback # POST from wallet ├── serviceSignerCallbackRedirect # GET redirect + page ├── serviceSignerStatus # polling └── fetchTargetIdentityInfo # getidentity, name + parent src/keydefiner.ts # VDXF key → i-address + update JSON