From 19fbaf1e6bce347bcdfd9aceec6a0f9b231c00dd Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Wed, 31 Jul 2024 21:10:19 -0400 Subject: [PATCH] feat: combine-invitation-makers exo - Takes two or more InvitationMaker exos and combines them into a new one. - Useful for combining exos that are already instantiated --- .../src/exos/combine-invitation-makers.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/orchestration/src/exos/combine-invitation-makers.js diff --git a/packages/orchestration/src/exos/combine-invitation-makers.js b/packages/orchestration/src/exos/combine-invitation-makers.js new file mode 100644 index 00000000000..e7b647e3ba6 --- /dev/null +++ b/packages/orchestration/src/exos/combine-invitation-makers.js @@ -0,0 +1,53 @@ +import { M } from '@endo/patterns'; +import { + prepareGuardedAttenuator, + makeSyncMethodCallback, +} from '@agoric/internal/src/callback.js'; +import { getMethodNames } from '@agoric/internal'; + +/** + * @import {InvitationMakers} from '@agoric/smart-wallet/src/types.js'; + * @import {Zone} from '@agoric/zone'; + */ + +// TODO use a helper from Endo https://github.com/endojs/endo/issues/2448 +/** + * Takes two or more InvitationMaker exos and combines them into a new one. + * + * @param {Zone} zone + * @param {import('@endo/patterns').InterfaceGuard[]} interfaceGuards + */ +export const prepareCombineInvitationMakers = (zone, ...interfaceGuards) => { + const methodGuards = interfaceGuards.map(ig => ig.payload.methodGuards); + const CombinedInterfaceGuard = M.interface( + 'CombinedInvitationMakers interface', + Object.assign({}, ...methodGuards), + ); + + const mixin = prepareGuardedAttenuator(zone, CombinedInterfaceGuard, { + tag: 'CombinedInvitationMakers', + }); + + /** + * @template {InvitationMakers[]} IM + * @param {IM} invitationMakers + * @returns {IM[number]} + */ + const combineInvitationMakers = (...invitationMakers) => { + const overrides = {}; + for (const invMakers of invitationMakers) { + // remove '__getInterfaceGuard__', '__getMethodNames__' + const names = getMethodNames(invMakers).filter(n => !n.startsWith('__')); + for (const key of names) { + overrides[key] = makeSyncMethodCallback(invMakers, key); + } + } + return mixin({ + overrides, + }); + }; + + return combineInvitationMakers; +}; + +/** @typedef {ReturnType} MakeCombineInvitationMakers */