Skip to content

Commit

Permalink
fix: hydrateHooks on the HTTP handler instead of addOffer
Browse files Browse the repository at this point in the history
Now we pass a real object as a hooks parameter.  This should make
it easier to use the wallet.addOffer programatically.
  • Loading branch information
michaelfig committed Mar 11, 2020
1 parent b50690b commit b3e214d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 26 deletions.
90 changes: 65 additions & 25 deletions packages/cosmic-swingset/lib/ag-solo/vats/lib-wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export async function makeWallet(
.map(p => harden(p[1]));
}

async function compileOfferDesc(id, offerDesc) {
async function compileOfferDesc(id, offerDesc, hooks = {}) {
const {
instanceRegKey,
contractIssuerIndexToRole = [], // FIXME: Only for compatibility with Zoe pre-Roles
Expand Down Expand Up @@ -379,10 +379,14 @@ export async function makeWallet(
roleOfferRules,
rolePurses,
);
return { zoeKind, publicAPI, offerRules, purses };
return { zoeKind, publicAPI, offerRules, purses, hooks };
}

async function addOffer(rawOfferDesc, requestContext) {
async function addOffer(
rawOfferDesc,
hooks = undefined,
requestContext = {},
) {
const { id } = rawOfferDesc;
const offerDesc = {
...rawOfferDesc,
Expand All @@ -394,7 +398,7 @@ export async function makeWallet(
updateInboxState(id, offerDesc);

// Start compiling the template, saving a promise for it.
idToCompiledOfferDescP.set(id, compileOfferDesc(id, offerDesc));
idToCompiledOfferDescP.set(id, compileOfferDesc(id, offerDesc, hooks));

// Our inbox state may have an enriched offerDesc.
updateInboxState(id, idToOfferDesc.get(id));
Expand Down Expand Up @@ -423,12 +427,6 @@ export async function makeWallet(
let ret = {};
let alreadyAccepted = false;
const offerDesc = idToOfferDesc.get(id);
const objectInvokeHookP = (obj, [hookMethod, ...hookArgs] = []) => {
if (hookMethod === undefined) {
return undefined;
}
return E(obj)[hookMethod](...hookArgs);
};
const rejected = e => {
if (alreadyAccepted) {
return;
Expand All @@ -452,14 +450,12 @@ export async function makeWallet(
idToOfferDesc.set(id, pendingOfferDesc);
const compiledOfferDesc = await idToCompiledOfferDescP.get(id);

const { publicAPI } = compiledOfferDesc;
const {
instanceInviteHook,
seatTriggerHook,
instanceAcceptedHook,
} = offerDesc;
const inviteP = objectInvokeHookP(publicAPI, instanceInviteHook);
publicAPI,
hooks: { publicAPI: publicAPIHooks = {}, seat: seatHooks = {} } = {},
} = compiledOfferDesc;

const inviteP = E(publicAPIHooks).getInvite(publicAPI);
const { seat, depositedP, cancelObj } = await executeOffer(
compiledOfferDesc,
inviteP,
Expand All @@ -472,17 +468,25 @@ export async function makeWallet(
// === AWAITING TURN ===
// =====================

objectInvokeHookP(seat, seatTriggerHook).catch(rejected);
// Don't wait for the offer to finish performing...
// we need to return control to our caller.
E(seatHooks)
.performOffer(seat)
.catch(e =>
assert(false, details`seatHooks.performOffer failed with ${e}`),
);

// Update status, drop the offerRules
depositedP.then(_ => {
// We got something back, so no longer pending or rejected.
alreadyAccepted = true;
const acceptOfferDesc = { ...pendingOfferDesc, wait: undefined };
idToOfferDesc.set(id, acceptOfferDesc);
updateInboxState(id, acceptOfferDesc);
return objectInvokeHookP(publicAPI, instanceAcceptedHook);
}, rejected);
depositedP
.then(_ => {
// We got something back, so no longer pending or rejected.
alreadyAccepted = true;
const acceptOfferDesc = { ...pendingOfferDesc, wait: undefined };
idToOfferDesc.set(id, acceptOfferDesc);
updateInboxState(id, acceptOfferDesc);
return E(publicAPIHooks).offerAccepted(publicAPI);
})
.catch(rejected);
} catch (e) {
rejected(e);
}
Expand All @@ -493,6 +497,41 @@ export async function makeWallet(
return Array.from(issuerPetnameToIssuer);
}

const hydrateHook = ([hookMethod, ...hookArgs] = []) => object => {
if (hookMethod === undefined) {
return undefined;
}
return E(object)[hookMethod](...hookArgs);
};

function hydrateHooks({
publicAPI: { getInvite, offerAccepted, ...publicAPIRest } = {},
seat: { performOffer, ...seatRest } = {},
...targetsRest
} = {}) {
const assertSpecs = [
[targetsRest, 'targets'],
[publicAPIRest, 'publicAPI hooks'],
[seatRest, 'seat hooks'],
];
for (const [rest, desc] of assertSpecs) {
assert(
Object.keys(rest).length === 0,
details`Unrecognized extra ${desc} ${rest}`,
);
}

return harden({
publicAPI: {
getInvite: hydrateHook(getInvite),
accepted: hydrateHook(offerAccepted),
},
seat: {
performOffer: hydrateHook(performOffer),
},
});
}

const wallet = harden({
addIssuer,
makeEmptyPurse,
Expand All @@ -502,6 +541,7 @@ export async function makeWallet(
getPurse: petnameToPurse.get,
getPurseIssuer: petname => purseToIssuer.get(petnameToPurse.get(petname)),
getIssuerNames: issuerToIssuerNames.get,
hydrateHooks,
addOffer,
declineOffer,
cancelOffer,
Expand Down
4 changes: 3 additions & 1 deletion packages/cosmic-swingset/lib/ag-solo/vats/vat-wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ function build(E, D, _log) {
};
}
case 'walletAddOffer': {
// We only need to do this because we can't reach addOffer.
const hooks = wallet.hydrateHooks(data.hooks);
return {
type: 'walletOfferAdded',
data: await wallet.addOffer(data, requestContext),
data: await wallet.addOffer(data, hooks, requestContext),
};
}
case 'walletDeclineOffer': {
Expand Down

0 comments on commit b3e214d

Please sign in to comment.