UNPKG

@agoric/deploy-script-support

Version:

Helpers and other support for writing deploy scripts

145 lines (130 loc) 4.66 kB
// @ts-check import { assert } from '@endo/errors'; import { E } from '@endo/far'; // Avoid pulling in too many dependencies like notifiers import { AmountMath } from '@agoric/ertp/src/amountMath.js'; /** * @import {Petname} from '@agoric/deploy-script-support/src/externalTypes.js'; * @import {Amount, Brand, Issuer, Payment, Purse} from '@agoric/ertp'; * @import {InvitationDetails, Keyword, Proposal} from '@agoric/zoe'; */ /** * @typedef {object} OfferHelperConfig * @property {ERef<Invitation>} [invitation] * @property {Partial<InvitationDetails>} [partialInvitationDetails] * @property {Proposal} proposal * @property {Record<Keyword, Petname>} paymentsWithPursePetnames * @property {Record<Keyword, Petname>} payoutPursePetnames */ /** * @param {ERef<any>} walletAdmin - an internal type of the * wallet, not defined here * @param {ERef<ZoeService>} zoe * @param {ERef<Purse<'set', InvitationDetails>>} zoeInvitationPurse */ export const makeOfferAndFindInvitationAmount = ( walletAdmin, zoe, zoeInvitationPurse, ) => { /** * @param {Record<string, any>} invitationDetailsCriteria * @returns {Promise<InvitationAmount>} invitationAmount */ const findInvitationAmount = async invitationDetailsCriteria => { const invitationAmount = await E(zoeInvitationPurse).getCurrentAmount(); // For every key and value in invitationDetailsCriteria, return an amount // with any matches for those exact keys and values. Keys not in // invitationDetails count as a match const matches = invitationDetail => Object.entries(invitationDetailsCriteria).every( ([key, value]) => invitationDetail[key] === value, ); const invitationValue = invitationAmount.value; assert(Array.isArray(invitationValue)); const matchingValue = invitationValue.find(matches); const value = matchingValue === undefined ? harden([]) : harden([matchingValue]); return AmountMath.make(invitationAmount.brand, value); }; const withdrawPayments = (proposal, paymentsWithPursePetnames) => { return Object.fromEntries( Object.entries(paymentsWithPursePetnames).map( ([keyword, pursePetname]) => { const purse = E(walletAdmin).getPurse(pursePetname); const amountToWithdraw = proposal.give[keyword]; const paymentP = E(purse).withdraw(amountToWithdraw); return [keyword, paymentP]; }, ), ); }; const withdrawInvitation = async invitationDetails => { // Let's go with the first one that fits our requirements const invitationAmount = await findInvitationAmount(invitationDetails); return E(zoeInvitationPurse).withdraw(invitationAmount); }; const getInvitation = (invitation, invitationDetails) => { if (invitation !== undefined) { return invitation; } assert( invitationDetails, `either an invitation or invitationDetails is required`, ); return withdrawInvitation(invitationDetails); }; const depositPayouts = (seat, payoutPursePetnames) => { const makeDepositInPurse = keyword => { const deposit = payment => { const pursePetname = payoutPursePetnames[keyword]; const purse = E(walletAdmin).getPurse(pursePetname); return E(purse).deposit(payment); }; return deposit; }; const handlePayments = paymentsP => { const allDepositedP = Promise.all( Object.entries(paymentsP).map(([keyword, paymentP]) => { const depositInPurse = makeDepositInPurse(keyword); return E.when(paymentP, depositInPurse); }), ); return allDepositedP; }; const paymentsPP = E(seat).getPayouts(); return E.when(paymentsPP, handlePayments); }; /** * @param {OfferHelperConfig} config */ const offer = async config => { const { invitation, partialInvitationDetails, proposal, paymentsWithPursePetnames, payoutPursePetnames, } = config; const invitationToUse = getInvitation(invitation, partialInvitationDetails); const invitationDetails = await E(zoe).getInvitationDetails(invitationToUse); const payments = withdrawPayments(proposal, paymentsWithPursePetnames); const seat = E(zoe).offer(invitationToUse, proposal, payments); const deposited = depositPayouts(seat, payoutPursePetnames); const offerResultP = E(seat).getOfferResult(); await E(walletAdmin).saveOfferResult( invitationDetails.handle, offerResultP, ); return { seat, deposited, invitationDetails, }; }; return { offer, findInvitationAmount, }; };