From b33287032a376b4adf8c5f695321a559550401ea Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Wed, 11 Mar 2020 05:03:00 -0600 Subject: [PATCH] feat: include requestContext in inboundCommand, and use it in wallet --- .../lib/ag-solo/vats/lib-wallet.js | 17 +++-- .../lib/ag-solo/vats/vat-wallet.js | 4 +- packages/cosmic-swingset/lib/ag-solo/web.js | 20 ++++-- .../wallet-frontend/src/components/Inbox.jsx | 65 +++++++++++-------- packages/wallet-frontend/update-agoric-cli.sh | 8 +++ 5 files changed, 73 insertions(+), 41 deletions(-) create mode 100755 packages/wallet-frontend/update-agoric-cli.sh diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/lib-wallet.js b/packages/cosmic-swingset/lib/ag-solo/vats/lib-wallet.js index 995dc45cabd..6d6ba051867 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/lib-wallet.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/lib-wallet.js @@ -387,14 +387,19 @@ export async function makeWallet( return { zoeKind, publicAPI, offerRules, purses }; } - async function propose(proposal) { - const { id } = proposal; - const newProposal = { ...proposal, status: undefined, wait: undefined }; - idToProposal.set(id, newProposal); - updateInboxState(id, newProposal); + async function propose(rawProposal, requestContext) { + const { id } = rawProposal; + const proposal = { + ...rawProposal, + requestContext, + status: undefined, + wait: undefined, + }; + idToProposal.set(id, proposal); + updateInboxState(id, proposal); // Start compiling the template, saving a promise for it. - idToCompiledProposalP.set(id, compileProposal(id, newProposal)); + idToCompiledProposalP.set(id, compileProposal(id, proposal)); // Our inbox state may have an enriched proposal. updateInboxState(id, idToProposal.get(id)); diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/vat-wallet.js b/packages/cosmic-swingset/lib/ag-solo/vats/vat-wallet.js index c236812286f..ba929c88adc 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/vat-wallet.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/vat-wallet.js @@ -26,7 +26,7 @@ function build(E, D, _log) { function getCommandHandler() { return { async processInbound(obj) { - const { type, data } = obj; + const { type, data, requestContext } = obj; switch (type) { case 'walletGetPurses': { if (!pursesState) return {}; @@ -45,7 +45,7 @@ function build(E, D, _log) { case 'walletPropose': { return { type: 'walletOfferAdded', - data: await wallet.propose(data), + data: await wallet.propose(data, requestContext), }; } case 'walletDeclineOffer': { diff --git a/packages/cosmic-swingset/lib/ag-solo/web.js b/packages/cosmic-swingset/lib/ag-solo/web.js index 5d4c0f3d28a..a93ccefd942 100644 --- a/packages/cosmic-swingset/lib/ag-solo/web.js +++ b/packages/cosmic-swingset/lib/ag-solo/web.js @@ -19,7 +19,13 @@ const send = (ws, msg) => { } }; -export function makeHTTPListener(basedir, port, host, inboundCommand) { +export function makeHTTPListener(basedir, port, host, rawInboundCommand) { + // Enrich the inbound command with some metadata. + const inboundCommand = (body, { headers: { origin } = {} } = {}) => { + const requestContext = { origin, date: Date.now() }; + return rawInboundCommand({ ...body, requestContext }); + }; + const app = express(); // HTTP logging. app.use( @@ -36,7 +42,9 @@ export function makeHTTPListener(basedir, port, host, inboundCommand) { fs.statSync(dapphtmldir); console.log(`Serving Dapp files from ${dapphtmldir}`); app.use(express.static(dapphtmldir)); - } catch (e) {} + } catch (e) { + // Do nothing. + } // serve the static HTML for the UI const htmldir = path.join(basedir, 'html'); @@ -80,7 +88,7 @@ export function makeHTTPListener(basedir, port, host, inboundCommand) { } // console.log(`POST /vat got`, req.body); // should be jsonable - inboundCommand(req.body).then( + inboundCommand(req.body, req).then( r => res.json({ ok: true, res: r }), rej => res.json({ ok: false, rej }), ); @@ -124,7 +132,7 @@ export function makeHTTPListener(basedir, port, host, inboundCommand) { console.log(id, 'client closed'); broadcasts.delete(ws); if (req.url === '/captp') { - inboundCommand({ type: 'CTP_CLOSE', connectionID }).catch(_ => {}); + inboundCommand({ type: 'CTP_CLOSE', connectionID }, req).catch(_ => {}); points.delete(connectionID); } }); @@ -132,7 +140,7 @@ export function makeHTTPListener(basedir, port, host, inboundCommand) { if (req.url === '/captp') { // This is a point-to-point connection, not broadcast. points.set(connectionID, ws); - inboundCommand({ type: 'CTP_OPEN', connectionID }).catch(err => { + inboundCommand({ type: 'CTP_OPEN', connectionID }, req).catch(err => { console.log(id, `error establishing connection`, err); }); ws.on('message', async message => { @@ -140,7 +148,7 @@ export function makeHTTPListener(basedir, port, host, inboundCommand) { // some things use inbound messages const obj = JSON.parse(message); obj.connectionID = connectionID; - await inboundCommand(obj); + await inboundCommand(obj, req); } catch (e) { console.log(id, 'client error', e); const error = e.message || JSON.stringify(e); diff --git a/packages/wallet-frontend/src/components/Inbox.jsx b/packages/wallet-frontend/src/components/Inbox.jsx index f7087cfa087..2edce55d255 100644 --- a/packages/wallet-frontend/src/components/Inbox.jsx +++ b/packages/wallet-frontend/src/components/Inbox.jsx @@ -79,21 +79,20 @@ const GreenChip = withStyles(theme => ({ }, }))(Chip); +const pet = petname => petname || '???'; + export default function Inbox() { const classes = useStyles(); const { state, dispatch } = useApplicationContext(); const { inbox } = state; - function formatDate(date) { - const options = { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }; - return new Date(date).toLocaleDateString('en-US', options); + function formatDateNow(stamp) { + const date = new Date(stamp); + const isoStamp = date.getTime() - date.getTimezoneOffset() * 60 * 1000; + const isoDate = new Date(isoStamp); + const isoStr = isoDate.toISOString(); + const match = isoStr.match(/^(.*)T(.*)\..*/); + return <>{match[1]} {match[2]}; } function handleCancel(id) { @@ -141,10 +140,11 @@ export default function Inbox() { {inbox.map( ({ + requestContext: { date, origin = 'unknown origin'} = {}, id, - id: date, instanceRegKey, - offerRulesTemplate, + instancePetname, + offerRulesTemplate: { offer = {}, want = {} }, status, wait, }) => ( @@ -154,42 +154,53 @@ export default function Inbox() { - - ({instanceRegKey}) - {formatDate(date)} + + At  + {date ? formatDateNow(date) : unknown time} via  + {origin} + + + + + + {pet(instancePetname)} +   + + {!instancePetname && ({instanceRegKey}) } + says: - {Object.entries(offerRulesTemplate.offer || {}).map( + {Object.entries(offer).map( ([role, { issuerPetname, pursePetname, brandRegKey, extent }], i) => ( {i === 0 ? 'Pay' : <>and pay}  {extent}   - {issuerPetname || '??'} -   + {pet(issuerPetname)} - {brandRegKey && ({brandRegKey}) } - from  + {!issuerPetname && <> ({brandRegKey})} from  - {pursePetname} + {pet(pursePetname)} ))} - {Object.entries(offerRulesTemplate.want || {}).map( + {Object.entries(want).map( ([role, { issuerPetname, pursePetname, brandRegKey, extent }], i) => ( - {i === 0 ? 'Receive' : <>and receieve}  + {i === 0 ? + (Object.keys(offer).length > 0 ? <>to receive : 'Receive') : + <>and receieve + }  {extent}   - {issuerPetname || '??'} -   + {pet(issuerPetname)} - {brandRegKey && ({brandRegKey}) } - into  + {!issuerPetname && <> ({brandRegKey})} into  - {pursePetname} + {pet(pursePetname)} ))} diff --git a/packages/wallet-frontend/update-agoric-cli.sh b/packages/wallet-frontend/update-agoric-cli.sh new file mode 100755 index 00000000000..506651e703f --- /dev/null +++ b/packages/wallet-frontend/update-agoric-cli.sh @@ -0,0 +1,8 @@ +#! /bin/sh +awb=../agoric-cli/agoric-wallet-build +set -xe +yarn build +git rm -rf "$awb" +rm -rf "$awb" +cp -r build "$awb" +git add "$awb"