Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | import { makeDefaultExo } from '@metamask/kernel-utils/exo';
import type {
ContactPoint,
ContactResponse,
RemotableSpec,
ServiceContactInfo,
ServiceDescription,
ServicePoint,
} from '@metamask/service-discovery-types';
/**
* Build a ContactPoint exo for a service with the Public access model.
*
* The returned exo reports its ServiceDescription on demand from
* `getServiceDescription()`, computing the description lazily so the
* contact URL (set post-issuance via the `getContactUrl` closure) is
* always current. It validates the matcher's registration callback via
* `confirmServiceRegistration(token)` by comparing against `expectedToken`,
* and returns `service` directly from `initiateContact()` (Public model).
*
* Registration tokens are single-use in this phase; once consumed,
* subsequent confirmation attempts throw.
*
* @param options - Construction options.
* @param options.name - Exo name, used in alleged type tags and the
* top-level spec property.
* @param options.service - The service exo to vend on `initiateContact()`.
* @param options.description - Natural-language description of the
* service as a whole.
* @param options.remotableSpec - Pre-computed remotable API spec.
* @param options.getContactUrl - Closure returning this endpoint's URL.
* Typically captures a `let` in the vat root that is assigned after
* `ocapURLIssuerService.issue(...)` resolves.
* @param options.expectedToken - The registration token the matcher must
* present to validate registration.
* @param options.providerTag - The provider-local identifier for the
* service. Must be unique among services hosted by this provider and
* must persist across restarts of the same logical service; the matcher
* uses (peerId, providerTag) as the dedup key when re-registrations
* arrive.
* @returns A ContactPoint exo.
*/
export function makeContactEndpoint(options: {
name: string;
service: ServicePoint;
description: string;
remotableSpec: RemotableSpec;
getContactUrl: () => string;
expectedToken: string;
providerTag: string;
}): ContactPoint {
const {
name,
service,
description,
remotableSpec,
getContactUrl,
expectedToken,
providerTag,
} = options;
let consumed = false;
return makeDefaultExo(`${name}ContactEndpoint`, {
async getServiceDescription(): Promise<ServiceDescription> {
const contact: ServiceContactInfo[] = [
{ contactType: 'public', contactUrl: getContactUrl() },
];
return harden({
apiSpec: harden({
properties: harden({
service: harden({
description: `The ${name} service.`,
type: harden({
kind: 'remotable' as const,
spec: remotableSpec,
}),
}),
}),
}),
description,
contact: harden(contact),
providerTag,
});
},
async confirmServiceRegistration(registrationToken: string): Promise<void> {
if (consumed) {
throw new Error(
`Registration token for ${name} has already been confirmed.`,
);
}
if (registrationToken !== expectedToken) {
throw new Error(
`Registration token mismatch for ${name}: matcher presented an unrecognized token.`,
);
}
consumed = true;
},
async initiateContact(): Promise<ContactResponse> {
return harden({ kind: 'public', service });
},
}) as unknown as ContactPoint;
}
|